Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate: how to disable automatic saving of dirty objects?

I was quite surprised to find out that Hibernate automatically saves dirty objects at the end of transaction, without explicit calls to something like

dao.save(object) 

I have in mind the situation described by this thread

My question is: is there a way to disable this behaviour? At first glance this automatic saving seems rather dangerous because you need to know which objects are connected to the session and which not and it seems pretty easy to save something by mistake. Can you tell me what the benefits of this automatic-saving approach are? I hardly see any. I'd like to always explicitly call dao.save(object) to update anything.

I heard of one possible workaround to this, which is using an entityInterceptor on your sessionFactory. This custom entityInterceptor would override the findDirty method to never find anything dirty, but in such case I suppose dao.save won't also work. Any ideas?

like image 859
machinery Avatar asked Oct 12 '12 12:10

machinery


People also ask

How to disable dirty checking in Hibernate?

A solution to this problem is to change the default configuration of FlushMode from auto to manual by setting FlushMode. MANUAL . In this way the dirty check mechanism will stop causing the aforementioned synchronization. Although the Session is only ever flushed when Session.

Does Hibernate automatically update changed objects?

Kind of mysterious – all you want to do would be to update the some component on your java logic and it is automatically saved in the database.

What is dirty checking Hibernate?

Hibernate monitors all persistent objects. At the end of a unit of work, it knows which objects have been modified. Then it calls update statement on all updated objects. This process of monitoring and updating only objects that have been changed is called automatic dirty checking in hibernate.


2 Answers

I agree, you should not flush manually. My experience of webapp developer said that FlushMode should be set to "AUTO". But sometimes I need to disable dirty check (for validation of data, validating data in database and data return by forms or services). For that I create a special class and disabled dirty check by changing the FLUSHMODE:

@Component public class ValidateRefPaysService implements IValidateRefPaysService {      ...      @Autowired     @Qualifier("sessionFactory")     private SessionFactory sessionFactory;      @Override     @Transactional(readOnly=true)      public void validate(RefPays refPays) throws BusinessException {                  try {             sessionFactory.getCurrentSession().setFlushMode(FlushMode.MANUAL);                      if ( refPays.getId() != null ) {                 RefPays refPaysBase = refPaysDAO.getById(refPays.getId());                 if ( refPaysBase != null )  {                     throw new BusinessException("id already exists in database.", "RefPays.savePays.id.alreadyexist", "refPays.savePays.id.alreadyexist");                 }             }         } finally {             sessionFactory.getCurrentSession().setFlushMode(FlushMode.AUTO);         }     } } 
like image 107
Grégory Avatar answered Oct 01 '22 00:10

Grégory


To disable automatic state management set the flush mode on your session to MANUAL. You can then call session.flush() to actually write out all dirty entities associated with your session.

like image 33
Stefan Haberl Avatar answered Sep 30 '22 23:09

Stefan Haberl