@RequestMapping("/testing")
@Transactional
public String testing(HttpServletRequest request, final ModelMap model)
{
Criteria criteria = session.getCurrentSession().createCriteria(Student.class);
criteria.setReadOnly(true);
criteria.add(Restrictions.eq("id", "ID12345"));
List<Student> result = criteria.list();
Student abc = result.get(0);
abc.setFirstname("AAA");
Criteria criteria2 = session.getCurrentSession().createCriteria(Student.class);
criteria2.setReadOnly(false);
criteria2.add(Restrictions.eq("id", "ID12345"));
result = criteria2.list();
Student abc2 = result.get(0);
abc2.setFirstname("BBB");
return "testing";
}
As the code above, it has setReadOnly
to true for criteria
, so firstName
will not be AAA
(in database), but it has reset the setReadOnly
to false for criteria2
, why the firstname
didn't become BBB
(in database)?
Ok, after some time of research, I managed to find out the reason.
While the first query load up the object, hibernate put the object in persistent context and mark the object as read-only
. Meaning the object will not be flushed in the end.
During second call to load up the object, hibernate fetch the object in persistent context instead of making call to database again, because the fetch is based on primary key. Since it is loaded from persistent context, it will be still in read-only
state.
In order to let the object back to flush-able again, we can use setReadOnly(Object entity, boolean readOnly)
to set back the readOnly
of the object.