我有这样的代码。我知道这个遗留代码可能不是最好的代码。
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中。
答案 0 :(得分:1)
如果您在事务中,它实际上不会将更改提交到Student
,它只是将它们刷新到数据库。当您在executeUpdate
对象上调用Query
时,它会在执行查询之前执行所有挂起更改的刷新,以确保数据的一致性。
您的loadStudentById
显然会返回一个托管实体,由Hibernate跟踪。它保留原始状态的副本,并将其与每次刷新时对象的当前状态进行比较。如果您不希望跟踪其中的更改,可以调用session.detach(student)
(如果使用Hibernate 5.2,它与EntityManager接口合并)。