Results 1 to 2 of 2

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

Hybrid View

  1. #1
    Join Date
    Dec 2004
    Location
    Taiwan
    Posts
    17

    Default <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 2nd, 2010 at 11:32 PM.

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,629

    Default

    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 at 03:02 AM.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •