Session.save正在更新hibernate中的数据

时间:2012-05-07 04:36:19

标签: hibernate

我试图在hibernate session.save()中为保存学生信息的代码示例。其中,学生姓名,班级,教师ID。

表:学生

SNO SNAME             SCLASS         TNO
----------- ----------------------------------------
1 J D Alex            3                1
2 Goaty               2                2
3 J D Paul            7                1

代码: -

Transaction tx1=session1.beginTransaction();
Object o2=session1.get(Student.class,new Integer(3));
((Student)o2).setSclass("8");
session1.save(o2);
log.info("loadStdYearlyInfo:class "+((Student)o2).getSclass());
tx1.commit();
session1.close();

保存数据并看到输出后,类值更新为8,学生ID为3

 SNO SNAME             SCLASS         TNO
    ----------- ----------------------------------------
    1 J D Alex            3                1
    2 Goaty               2                2
    3 J D Paul            8                1

[07/May/2012:10:03:06] info ( 3500): CORE3282: stdout: Hibernate: /* load com.aims.beans.Student */ select student0_.sno as sno0_, student0_.sname as sname1_0_, student0_.sclass as sclass1_0_, student0_.tno as tno1_0_ from student student0_ where student0_.sno=?
[07/May/2012:10:03:06] info ( 3500): CORE3282: stdout: loadStdYearlyInfo:class 8
[07/May/2012:10:03:06] info ( 3500): CORE3282: stdout: Hibernate: /* update com.aims.beans.Student */ update student set sname=?, sclass=?, tno=? where sno=?
[07/May/2012:10:03:06] info ( 3500): CORE3282: stdout: loadStdYearlyInfo2

如何更新数据库中的学生班级值?.save意味着插入数据。但是这里的值已更新。请告诉我。如有任何问题?。如果有任何错误,那么抱歉。

3 个答案:

答案 0 :(得分:7)

这是Hibernate的预期行为。

当hibernate会话加载记录时,其实例将处于persistent状态并由此会话管理。如果更改持久性实例的值,则将它们视为脏。在刷新过程中(即Session.flush()),hibernate将找出所有脏实例(我们称之为此进程automatic dirty checking)并生成并发出必要的SQL以便更新相应的DB记录确保DB记录与JVM中保存的相应实例具有相同的状态。

休眠会话的刷新行为由FlushMode确定。默认情况下,它是FlushMode.AUTO,这意味着在提交事务或执行查询之前将自动调用session.flush()。因此,在您的代码中,虽然您没有显式调用session.flush(),但仍会发生刷新过程以发出这些UPDATE语句。

关于代码的一些评论:

Transaction tx1=session1.beginTransaction();   

/**
 * o2 is the in the persistent state and managed by session1
 */
Object o2=session1.get(Student.class,new Integer(3));

/**
 *As the value of o2 is changed , it becomes dirty and hibernate will issue an UPDATE SQL 
 *for it during flushing.
 */
 ((Student)o2).setSclass("8");

/**
 * save() only has effect on the transient instance. Nothing will 
 * be done when calling it on the persistent instance . So removing this line of code 
 * still produces the same result.
 */
session1.save(o2);
log.info("loadStdYearlyInfo:class "+((Student)o2).getSclass());

/**
 *I believe default FlushMode (FlushMode.AUTO) is used in here ,so session.flush()  will be invoked implicitly before tx1.commit().
 *Automatic dirty checking occurs and UPDATE SQL is generated and issued to the DB 
 *to update the dirty o2 instance
 */ 
tx1.commit();
session1.close();

答案 1 :(得分:1)

这是一种预期的行为。

get返回的对象是持久性。对于持久对象,save的调用基本上是被忽略的。但是Hibernate会自动跟踪持久对象中的更改并相应地更新数据库,因此update语句。

答案 2 :(得分:0)

我认为这是因为您正在处理交易。当您提交事务时,它会自动刷新对已加载实体的任何更改,在本例中为您的Student对象 它不保存对象,因为它已经有一个附加到会话的唯一标识符 我原本以为Hibernate会抛出一个异常,因为你试图保存已经附加的对象。

我希望这可以帮助你。