HIBERNATE JBoss.org
 |  Register  | 
     
News 
About 
   Feature List 
   Road Map 
Documentation 
   Related Projects 
   External Documentation 
Download 
Forum & Mailinglists 
Support & Training 
JIRA Issue Tracking
Wiki Community Area


Hibernate Public Training Courses


Get Hibernate in Action eBook!


JavaWorld 2003 Finalist


Jolt Award 2004 Winner
      
Documentation > Community Area > Hibernate Transaction Manager with PicoContainer and Nanning

Hibernate Transaction Manager with PicoContainer and Nanning

In some cases, you may want to use PicoContainer to manage your system.

PicoContainer can help you creating and managing Object in an IOC way.

Another case, AOP is the best way to manage transaction.

So, in my system, I use PicoContainer and Nanning manage my Hibernate Transaction.

First, let's see some interface, Dao and TxManager:

public interface Dao {
    void update();
    Object create();
    ... // sample method
}

public interface TxManager {
    void begin();
    void commit();
    void rollback();
}

In general, by legacy code, we need to make a Dao extends an AbstractDao, that has the transaction mehtod, like commit().

public class AbstractDao {
    void begin();
    void commit();
    void rollback();
}

public class MyDao extends AbstractDao {
    public void update(...){
         super.begin();
         session.update();
         super.commit();
    }
}

It is no doubt that the Transaction is one Aspect of the Dao class.

So, we should use some AOP tools to seprate the aspect.

A problem is , we must control the same Session for the TransactionAspect and the Dao. Of course we can use ServiceLocator or other Singletons.

But that is not the IOC way. we should inject the Session to the Objects.

We can use ObjectReference in PicoContainer holding the Session. And also we can use other persistent strategy, like use JDBC directly.


public interface ObjectReference{
    Object get();
    void set(Object obj);
}

public class DatabaseReference implements ObjectReference{
    private Session session;
    public DatabaseReference(){
     //  get or create Session from ThreadLocal
    }
    Objcet get(){
      return session;
    }

    void set(Object obj){}

}

We implement sample TxManager and Dao. It is nothing different.:

public class TxManagerImpl implements TxManager {
    private Session session;
    private Transaction tx;
    public TxManagerImpl(DatabaseReference dref) {
       this.session = (Session)dref.get();
    }
    public void begin() {
         this.tx = session.beginTransaction();
    }
    public void commit() {
        tx.commit();
    }


    public void rollback() {
        tx.rollback();
    }
}


public class SampleDaoImpl implements SampleDao {

    private Session session;

    public SampleDaoImpl(DatabaseReference dref){
        this.session = (Session)dref.get();
    }


    void update(Po p) {
        session.save(Po...)
    }
}

Here is the important Aspect, I use the NanoContainer's nanning component.

It has an advise interceptor.

public class TransactionAspect implements Aspect {
    Pointcut transactionPointcut = P.all(); 
    TxManager txManager;

    public TransactionAspect(TxManager transactionManager) {
        this.txManager = transactionManager;
    }

    public void introduce(AspectInstance arg0) {
    }

    public void advise(AspectInstance instance) {
       transactionPointcut.advise(instance, new MethodInterceptor() {
            public Object invoke(Invocation invocation) throws Throwable {
                txManager.begin();
                try {
                   Object o = invocation.invokeNext();
                   txManager.commit();
                   return o;
                } catch (Exception e) {
                   txManager.rollback();
                   throw e;
                }
            }
        });
    }
}

Finally, we prepare the pico instances.


        MutablePicoContainer pico = new DefaultPicoContainer(
               new CachingComponentAdapterFactory(
                        new NanningComponentAdapterFactory()));
      
        pico.registerComponentImplementation(TxManager.class,
                TxManagerImpl.class);
        pico.registerComponentImplementation(TransactionAspect.class,
                TransactionAspect.class);
        pico.registerComponentImplementation(SampleDao.class, 
                SampleDaoImpl.class);
        pico.getComponentInstances();

        Dao dao = (Dao) pico.getComponentInstance(SampleDao.class);

        dao.update(//a Po here);

Form the log, we see, it starts transaction and commits successfully.

Another thing we solved is the Transaction between several Dao. We can use a class encapsulate the several Dao, and make transaction aspect cross cutting the wrapper class. So, All the Dao in the wrapper are transactional.

Welcome send mail to me to discuss this implementation: icecloud(AT)sina.com or limo(AT)staff.zotn.com

This article is just translated from my blog http://www.nona.name :

http://icecloud.51.net/blog/archives/000015.html

I'm from China, so, do I make myself understood with my poor English??

      

coWiki