Search code examples
springhibernatetransactional

@Transactionnal + Hibernatetemplate Without saving dirty objects


I already search in forums, and i tried many things without succes.

I want at the end on a transactional method, and only at the end, to save only hibernate object for whom i will use explicitly the Hibernate getHibernateTemplate().saveOrUpdate() method, and NOT dirty ones, that i only modify using setters.

My need will be clearer after reading my service layer code:

For simplicity purpose, i will summarize my code.

Service layer:

@Service("cartService")
public class CartServiceImpl extends AbstractServiceImpl<Cart> implements
        CartService {

   @Autowired 
   private CartDao cartDao;

   @Transactional(readOnly = false)
   public Cart updateCart1(){

            Cart cartA = cartDao.findById(1);
            cartA.setTotal=(5);

            Cart cartB = cartDao.findById(1);
            cartB.setTotal=(5);     
            CartDao.Update(cartB);
   }
}

So, what i need, is at the end of the method updateCart1() is to save the change of cartB, BUT Not to save the change of cartA.

Dao layer:

NB: cartDao's methods (findById, saveOrUpdate) call the HibernateTemplate one.

public T update(T entite) {
    getHibernateTemplate().saveOrUpdate(entite);
    return entite;
}

public T findById(Serializable id) {
    return getHibernateTemplate().get(this.clazz, id);
}

I didn't want that Dao's method act on database outside a transactionnal service layer method. And i wanted them to be executed in database at the end of a transaction defined on the service layer. Thus, in hibernate spring configuration file:

<prop key="connection.autocommit">false</prop> 

Note that i am using OpenSessionInViewFilter for Lazyu loading purpose. So in my XML file:

<filter>
  <filter-name>OpenSessionInViewFilter</filter-name>
  <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
  <init-param>
     <param-name>singleSession</param-name>
     <param-value>false</param-value>
  </init-param> 
</filter>

NB: These cart cartDao's methods are working fine in a normal scenario. But not in the one i'm describing. And "@Transactional" is correctly configured and work fine two.

Problem: With this code, i get the two objects (cartA and cartB) changed in database, while i dont want to modify cartA, for whom i didn't call explicitly the HibernateTemplate's saveOrUpdate method.

After searching in forums, i tried to make the hibernate FLUSH mode to FLUSH_NEVER. But at the execution of CartDao.Update(cartB) i get this exception:

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.

Please, can you help me?


Solution

  • You could call

    getHibernateTemplate().getSession().evict(cartA);
    

    to remove it from the session.

    The best option though is to not modify cartA. If you need to calculate something using a cartA property you could make a copy of that property.