Question

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?

Était-ce utile?

La 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.

Autres conseils

You can use org.hibernate.StatelessSession interface instead of org.hibernate.Session.

In javadocs you see:

A stateless session does not implement a first-level cache nor interact with any second-level cache, nor does it implement transactional write-behind or automatic dirty checking, nor do operations cascade to associated instances. Collections are ignored by a stateless session. Operations performed via a stateless session bypass Hibernate's event model and interceptors. Stateless sessions are vulnerable to data aliasing effects, due to the lack of a first-level cache.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top