Hibernate getNamedQuery执行其他UPDATE TABLE

时间:2017-05-04 11:29:33

标签: java sql hibernate named-query

我有这样的代码。我知道这个遗留代码可能不是最好的代码。

final Student student = loadStudentById(13);
student.setLastAccessedTime(new Date());
student.setNote(20);
updateWithHQLUsingNamedQueries(student);//HERE WE UPDATE BOTH FIELDS USING NAMEDQUERIES

 private void updateWithHQLUsingNamedQueries(final Student student){
     final Query query = session.getNamedQuery("namedQuery"); 
     query.setParameter("lastAccessedTime",student.getLastAccessedTime());
     query.setParameter("note",student.getNote());
     query.setParameter("c01",c01Field);
     query.executeUpdate();//HERE HIBERNATE UPDATE THE STUDENT LIKE session.update(student);
 }

我们也在使用

@org.hibernate.annotations.DynamicUpdate(value=true)
@org.hibernate.annotations.SelectBeforeUpdate(value=true)

一切正常但是在SQL日志中我可以看到第一个更新,就像这样的常规更新。

HIBERNATE UPDATE

update com.models.Student HIBERNATE MESSAGE
update student set lastAccessedTime=:time and note=:note where id=:id

后来我看到了namedQueries的更新

update student set c01=:c01 and lastAccessedTime=:time and note=:note where id=:id

我的问题是?

为什么Hibernate在常规更新中提交Student字段,我的意思是我在executeUpdate之前做了类似的事情?学生不在任何地方。

session.update(student);

我知道他们只更新脏字段,因为我正在使用DynamicTrue,也许最后一次更新(NamedQuery)似乎浪费了。但为什么Hibernate像定期更新一样提交学生对象?导致两次更新?降低性能?

感谢@coladit的答案,但如果我修改我的代码设置另一个属性,如

final Student student = loadStudentById(13);
student.setLastAccessedTime(new Date());
student.setNote(20);
student.setAnotherProperty(value);//THIS CHANGE IS PERSISTED IN DB

flush是否在DB中持续保存属性?????因为我修改了属性并且即使在namedQuery没有持久化的情况下也会更新到DB中。

1 个答案:

答案 0 :(得分:1)

如果您在事务中,它实际上不会将更改提交到Student,它只是将它们刷新到数据库。当您在executeUpdate对象上调用Query时,它会在执行查询之前执行所有挂起更改的刷新,以确保数据的一致性。

您的loadStudentById显然会返回一个托管实体,由Hibernate跟踪。它保留原始状态的副本,并将其与每次刷新时对象的当前状态进行比较。如果您不希望跟踪其中的更改,可以调用session.detach(student)(如果使用Hibernate 5.2,它与EntityManager接口合并)。