Announcement Announcement Module
Collapse
No announcement yet.
<tx:advice> and <aop:pointcut> seems not working for Abstract Dao Pattern Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • <tx:advice> and <aop:pointcut> seems not working for Abstract Dao Pattern

    Environment : spring-framework-2.5.6.SEC01 , hibernate-distribution-3.3.2.GA , hibernate-entitymanager-3.4.0.GA

    I am trying to use <tx:advice> and <aop: pointcut> to declare my transaction in my spring xml file , the config is as following :

    Code:
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
      <tx:attributes>
        <tx:method name="get*"    read-only="true"/>
        <tx:method name="save*"   propagation="REQUIRED"/>
        <tx:method name="update*" propagation="REQUIRED"/>
        <tx:method name="delete*" propagation="REQUIRED"/>
        <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
      </tx:attributes>
    </tx:advice>
    
    <aop:config>
      <aop:pointcut id="methods" expression="execution(* destiny.data.mining.DaoMining.*(..))"/>
      <aop:advisor advice-ref="txAdvice" pointcut-ref="methods"/>
    </aop:config>  
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
     
    <bean id="daoMining" class="destiny.data.mining.DaoMiningJpaImpl"/>
    In my DaoMiningJpaImpl , it is very simple :
    Code:
    public class DaoMiningJpaImpl implements DaoMining
    {
      @PersistenceContext(unitName="mining")
      private EntityManager em;
    
      @Override
      public Person get(Serializable id){
        return em.find(Person.class, id);
      }
    
      @Override
      public Person save(Person p){
        return em.merge(p);
      }
    
      @Override
      public Person update(Person p)  {
        return em.merge(p);
      }
    
      @Override
      public void delete(Person p) {
        em.remove(em.merge(p));
      }
    
    }
    It works very well ... Untill.... I want to implement an "Abstract Dao Pattern" :

    First , I created an AbstractDao :
    Code:
    public interface AbstractDao<T>
    {
      public T get(Serializable id);  
      public T save(T t); 
      public T update(T t);
      public void delete(T t);
    }
    Then I created an AbstractDaoJpaImpl that implements AbstractDao :
    Code:
    public abstract class AbstractDaoJpaImpl<T> implements AbstractDao<T> , Serializable
    {
      private EntityManager em;
      private Class<T> clazz;
      
      public AbstractDaoJpaImpl(EntityManager em , Class<T> clazz)  {
        this.em = em;
        this.clazz = clazz;
      }
      
      @Override
      public T get(Serializable id)  {
        return em.find(clazz, id);
      }
    
      @Override
      public T save(T t)
      {
        //em.getTransaction().begin();
        em.persist(t);
        //em.getTransaction().commit();
        return t;
      }
    
      @Override
      public T update(T t)  {
        return em.merge(t);
      }
    
      @Override
      public void delete(T t)  {
        em.remove(em.merge(t));
      }
    }
    Then I created DaoMiningImpl that extends AbstractDaoJpaImpl :
    Code:
    public class DaoMiningImpl extends AbstractDaoJpaImpl<Person> implements DaoMining
    {
      public DaoMiningImpl(EntityManagerFactory emf)
      {
        super(emf.createEntityManager(), Person.class);
      }
    }
    Then I change my xml file to :
    Code:
    <aop:config>
      <aop:pointcut id="methods" expression="execution(* destiny.utils.AbstractDao.*(..))"/>
      <aop:advisor advice-ref="txAdvice" pointcut-ref="methods"/>
    </aop:config>  
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
    
    <bean id="daoMining" class="destiny.data.mining.DaoMiningImpl">
      <constructor-arg ref="entityManagerFactory"/>
    </bean>
    But now , the transaction fails , all save/update/delete actions are not written to DB.
    It seems <tx:advice> and <aop: pointcut> cannot declare transactions into this Abstract Dao Pattern ...

    I tried to add @Transactional to DaoMiningImpl and AbstractDaoJpaImpl , but both not working.

    The only way to make it working is adding em.getTransaction().begin() and em.getTransaction().commit() to AbstractDaoJpaImpl :
    Code:
      @Override
      public T save(T t)
      {
        em.getTransaction().begin();
        em.persist(t);
        em.getTransaction().commit();
        return t;
      }
    But that's not what I want . I want a declarative transaction

    Could anybody tell me how to solve it ? thanks !
    Last edited by smallufo; Jan 3rd, 2010, 12:32 AM.

  • #2
    You cannot apply transactions to the AbstractDao because you are issueing internal method calls. Internal calls don't pass through a proxy and hence don't get transactions applied. Next to that you are using the EntityManagerFactory to create a NEW EntityManager outside the scope of spring, you should be using the injected EntityManager.

    You can try to get it to work by changing the usage of EntityManagerFactory and by changing your pointcut to also apply to subclasses.

    Code:
    <aop:pointcut id="methods" expression="execution(* destiny.utils.AbstractDao+.*(..))"/>
    Although if you have a naming convention for your daos I would change it to apply to that.

    Check chapter 6.6.1 of the reference guide for more information on proxies.
    Last edited by Marten Deinum; Jan 3rd, 2010, 04:02 AM.

    Comment

    Working...
    X