Spring @Transactional和继承

时间:2013-01-04 07:42:27

标签: java spring transactions spring-transactions transactional

我有一个基于泛型的DAO类,它是我项目中所有其他DAO类的基础,并包含常用功能:

public class Dao<E> {

    private SessionFactory factory;

    public void setSessionFactory(SessionFactory factory) {
        this.factory = factory;
    }

    public E get(int id) {
        // ....
    }

    public void save(E entity) {
        // ...
    }

    public void delete(E entity) {
        // ...
    }

}

在我的项目中,我使用多个数据源,指向不同的数据库,因此,我有多个会话和事务管理器:

<bean id="factory1" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="source1" />
</bean>

<bean id="manager1" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="factory1" />
</bean>

<bean id="factory2" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="source2" />
</bean>

<bean id="manager2" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="factory2" />
</bean>

现在我想创建几个在不同数据库上运行的DAO:

@Repository
@Transactional("manager1")
public class Dao1 extends Dao<Entity1> {

    @Overrides
    @Autowired
    @Qualifier("factory1")
    public void setSessionFactory(SessionFactory factory) {
        super.setSessionFactory(factory);
    }

}

@Repository
@Transactional("manager2")
public class Dao1 extends Dao<Entity2> {

    @Overrides
    @Autowired
    @Qualifier("factory2")
    public void setSessionFactory(SessionFactory factory) {
        super.setSessionFactory(factory);
    }

}

但问题是,来自Dao的所有公共方法都没有@Transactional来自子类,因此不会发生事务管理。我能想到的唯一选择是覆盖父类方法,因此它们在继承的类中定义,因此由@Transactional处理:

@Repository
@Transactional("manager1")
public class Dao1 extends Dao<Entity1> {

    @Overrides
    @Autowired
    @Qualifier("factory1")
    public void setSessionFactory(SessionFactory factory) {
        super.setSessionFactory(factory);
    }

    @Overrides
    public Entity1 get(int id) {
        return super.get(id);
    }

    @Overrides
    public void save(Entity1 entity) {
        super.save(entity);
    }

    @Overrides
    public void delete(Entity1 entity) {
        super.delete(entity);
    }

}

但是我需要在每个 DAO类中执行此操作,代码将无处不在......

有没有更好的方法如何在所有类中共享通用功能,并且还具有声明式事务管理的所有好处?

3 个答案:

答案 0 :(得分:2)

如果你不介意super类也是@Transactional,你应该把注释放在super DAO上。如果您介意的话,我建议创建一个扩展类TransactionalDao,它将扩展主DAO并为@Transactional,所有应该@Transactional的DAO也将扩展它:

public class Dao<E> {

    private SessionFactory factory;

    public void setSessionFactory(SessionFactory factory) {
        this.factory = factory;
    }

    public E get(int id) {
        // ....
    }

    public void save(E entity) {
        // ...
    }

    public void delete(E entity) {
        // ...
    }

}

@Transactional
public class TransactionalDao<E> extends Dao<E>{

    private SessionFactory factory;

    public void setSessionFactory(SessionFactory factory) {
        this.factory = factory;
    }

    public E get(int id) {
        return super.get(id);
    }

    public void save(E entity) {
        super.save(entity);
    }

    public void delete(E entity) {
        super.delete(entity);
    }
}

现在扩展类看起来像这样:

@Repository
@Transactional("manager1") // You'd probably still want the @Transactional for new methods
public class Dao1 extends TransactionalDao<Entity1> {

    @Overrides
    @Autowired
    @Qualifier("factory1")
    public void setSessionFactory(SessionFactory factory) {
        super.setSessionFactory(factory);
    }   
}

这样你只需要做一次这个super包装的东西。

答案 1 :(得分:0)

您是否尝试将@Transaction放在父DAO类的方法上?

public class Dao<E> {

    private SessionFactory factory;

    public void setSessionFactory(SessionFactory factory) {
        this.factory = factory;
    }
    @Transactional(readOnly = true)
    public E get(int id) {
        // ....
    }
    @Transactional
    public void save(E entity) {
        // ...
    }
    @Transactional
    public void delete(E entity) {
        // ...
    }
}

这样当你在DAO1上调用save时,它将从子类中获取类级别的@Transaction(它将指定要使用的TX管理器),然后从父级的save方法中获取方法级别的@Transactional。

答案 2 :(得分:-2)

不应在任何地方添加@Transactional注释,而应使用AOP based Transaction Management之类的 -

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean>

  <tx:advice id="txAdvice" transaction-manager="txManager">  
  <tx:attributes>  
    <tx:method name="get*" read-only="true"/>  
    <tx:method name="*"/>
  </tx:attributes>
  </tx:advice>

在服务层使用交易是一种好习惯。