3

我正在尝试在休眠 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 意味着插入数据。但是这里的值是更新的。请让我知道。如果有任何问题?如果有任何问题,对不起。

4

3 回答 3

7

This is the expected behaviour of Hibernate.

当休眠会话加载记录时,其实例将处于持久状态并由该会话管理。如果持久实例的值发生了变化,它们就被认为是脏的。在刷新过程中(即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();
于 2012-05-07T06:55:12.250 回答
1

It's an expected behaviour.

Object returned by get is persistent. Call of save for persistent object is, basically speaking, ignored. But Hibernate automatically tracks changes in persistent object and updates the database accordingly, hence the update statement.

于 2012-05-07T06:29:59.460 回答
0

I think it is because you are working with transactions. When you commit a transaction it automatically flushes any changes to an already loaded entity, in this case your Student object.
It does not save the object because it already has an unique identifier attached to the session.
I would have thought Hibernate would have thrown an exception because you tried to save an already attached object.

I hope this helps you out.

于 2012-05-07T05:00:04.597 回答