Reputation: 4991
I have a code like this. This a legacy code i know maybe is not the best one.
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);
}
Also we are using
@org.hibernate.annotations.DynamicUpdate(value=true)
@org.hibernate.annotations.SelectBeforeUpdate(value=true)
Everything works OK but in the SQL logging i can see two updates the first like a regular update like this.
A HIBERNATE UPDATE
update com.models.Student HIBERNATE MESSAGE
update student set lastAccessedTime=:time and note=:note where id=:id
And later i see the update of the namedQueries
update student set c01=:c01 and lastAccessedTime=:time and note=:note where id=:id
My question is?
Why Hibernate commits the Student fields in a regular update i mean like i was doing something like just before the executeUpdate? The student is not commited anywhere.
session.update(student);
I know they are updating only the dirty fields because i am using DynamicTrue and maybe the last update(NamedQuery) seems wasted. But WHY Hibernate commits the student object like a regular update??? Resulting in two updates? degrading performance?
Thanks to @coladit for your answer but if i modify my code setting a another property like this
final Student student = loadStudentById(13);
student.setLastAccessedTime(new Date());
student.setNote(20);
student.setAnotherProperty(value);//THIS CHANGE IS PERSISTED IN DB
Does flush do the property persisted in DB????? Because i modify the property and is updated into the DB even when the namedQuery doesn't persisted..
Upvotes: 0
Views: 511
Reputation: 5095
It does not actually commit the changes to the Student
if you are in a transaction, it merely flushes them to the database. When you call executeUpdate
on the Query
object, it performs a flush of all pending changes before executing your query, in order to ensure data consistency.
Your loadStudentById
apparently returns a managed entity, which is kept track of by Hibernate. It keeps a copy of the original state and compares it to the current state of the object on every flush. If you don't want the changes in it to be tracked, you can call session.detach(student)
(if using Hibernate 5.2 where it's merged with the EntityManager interface).
Upvotes: 1