简体   繁体   中英

Coherence and container managed transactions

I'm implementing simultaneous write into database and Oracle Coherence 3.7.1 and want to make whole operation transactional.

I would like to have a critique on my approach.

Currently, I've created façade class like this:

public class Facade {
   @EJB
   private JdbcDao jdbcDao;
   @EJB
   private CoherenceDao coherenceDao;

   @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
   private void updateMethod(List<DomainObject> list) {
      jdbcDao.update(list);
      coherenceDao.update(list);
   }
}

I guess JDBC DAO would not need to do anything specific about transactions, it something happens Hibernate would throw some kind of RuntimeException.

public class JdbcDao {
   private void update(List<DomainObject> list) {
       // I presume there is nothing specific I have to do about transactions.
       // if I don't catch any exceptions it would work just fine
   }
}

Here is interesting part. How do I make Coherence support transactions? I guess I should open coherence transaction inside update() method and on any exceptions inside it I should throw RuntimeException myself?

I currently thinking of something like this:

public class CoherenceDao {
   private void update(List<DomainObject> list) {
      // how should I make it transactional?
      // I guess it should somehow throw RuntimeException?

      TransactionMap mapTx = CacheFactory.getLocalTransaction(cache);
      mapTx.setTransactionIsolation(TransactionMap.TRANSACTION_REPEATABLE_GET);
      mapTx.setConcurrency(TransactionMap.CONCUR_PESSIMISTIC);

      // gather the cache(s) into a Collection
      Collection txnCollection = Collections.singleton(mapTx);

      try {
         mapTx.begin();

         // put into mapTx here

         CacheFactory.commitTransactionCollection(txnCollection, 1);
      } catch (Throwable t) {
         CacheFactory.rollbackTransactionCollection(txnCollection);
         throw new RuntimeException();
      }

   }
}

Would this approach work as expected?

I know that you asked this question a year ago and my answer now might not be as much as value for you after a year but I still give it a try.

What you are trying to do works as long as there is no RuneTimeException after the method call of coherenceDao.update(list); You might be assuming that you don't have any line of codes after that line but that's not the whole story.

As an example: You might have some deferrable constraints in your Database. Those constraints will be applied when the container is trying to commit the transaction which is on method exit of updateMethod(List<DomainObject> list) and after your method call to coherenceDao.update(list) . Another cases would be like a connection timeout to database after that coherenceDao.update(list) is executed but still before the transaction commit. In both cases your update method of CoherenceDAO class is executed safe and sound and your coherence transaction is not rollbacked anymore which will put your cache in an inconsistent state because you will get a RuneTimeException because of those DB or Hibernate Exceptions and that will cause your container managed transaction to be rollbacked!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM