首页 文章

带有2个事务管理器的@EnableTransactionManagement注释

提问于
浏览
23

我使用 @Configuration 注释来配置spring而不是xml文件 . 我正在配置具有不同会话工厂和不同事务管理器的2个数据源 . 我在这里遇到了 @EnableTransactionManagement 注释的问题 . 我在其文档中读到,

@EnableTransactionManagement更灵活;它将回退到容器中任何PlatformTransactionManager bean的类型查找 . 因此,名称可以是“txManager”,“transactionManager”或“tm”:它无关紧要 .

这意味着我给方法的任何名称,它总是会搜索返回 PlatformTransactionManager 对象的方法,而我有2个transactionmanagers . 现在问题是,当我测试这个类时,它给了我错误:

org.springframework.beans.factory.NoSuchBeanDefinitionException:没有定义类型为[org.springframework.transaction.PlatformTransactionManager]的唯一bean:期望的单个bean但找到2

我甚至试图拥有2个不同的配置类但是徒劳无功 . 在xml配置中,情况并非如此 . 我用两个 <tx:annotation-driven transaction-manager="" /> 标签注册了我的两个事务管理器,它工作正常 . 但是这里不能用注释做同样的事情 .

如果我想在Spring注释配置类中配置2个具有2个不同事务管理器的数据源,我该怎么办?

6 回答

  • 0

    在配置类中,使用 @EnableTransactionManagement 注释 .

    在此类中定义事务管理器:

    @Bean(name="txName")
        public HibernateTransactionManager txName() throws IOException{
            HibernateTransactionManager txName= new HibernateTransactionManager();
            txName.setSessionFactory(...);
            txName.setDataSource(...);
            return txName;
       }
    

    在您的类/方法中执行事务作业,注释如下:

    @Transactional("txName")
    

    要么

    @Transactional(value = "txName")
    

    这就是如何将名称限定的事务管理器绑定到您需要的位置 . 您现在可以拥有任意数量的事务管理器,并根据需要随时使用它 .

  • 32

    万一有人遇到这个问题,我找到了一个解决方案:

    @Configuration
    @EnableTransactionManagement
    @DependsOn("myTxManager")
    @ImportResource("classpath:applicationContext.xml")
    public class AppConfig implements TransactionManagementConfigurer {
    
    @Autowired
    private PlatformTransactionManager myTxManager;
    
    ...
    
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return this.myTxManager;
    }
    

    通过这种方式,您可以使用xml配置中定义的特定txManager .

    如果要定义服务级别使用的txManager,则应 @Configuration 类中的 @EnableTransactionManagement 注释,并在 @Transactional 注释中指定txManager,例如:

    @Service
    @Transactional(value="myTxManager", readOnly = true)
    public class MyServiceImpl implements MyService { ... }
    
  • 5

    来自java doc

    对于那些希望在@EnableTransactionManagement和要使用的确切事务管理器bean之间 Build 更直接关系的人,可以实现TransactionManagementConfigurer回调接口 - 注意下面的implements子句和@Override-annotated方法:

    您的 @Configuration 类需要实现 TransactionManagementConfigurer 接口 - 实现 annotationDrivenTransactionManager ,它将返回应该使用的 transactionManager 的引用 .

  • 8

    我不确定你为什么使用两个TransactionManagers . 您可以考虑通过AbstractRoutingDataSource将相同的TransactionManager用于多个数据源 . 请参考

    http://blog.springsource.org/2007/01/23/dynamic-datasource-routing/

    关于其使用的样本 .

  • 0

    其他一些答案暗示使用两个事务管理器在某种程度上是错误的;但是,Spring的XML配置允许使用在线文档中所述的多个事务管理器(如下所示) . 不幸的是,似乎没有办法让 @EnableTransactionManagement 注释以类似的方式工作 . 因此,我只需使用 @ImportResource 注释来加载包含 <tx:annotation-driven/> 行的XML文件 . 这允许您为大多数事情获取Java配置,但仍然使用带有可选事务管理器限定符的 @Transactional .

    http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/transaction.html

    大多数Spring应用程序只需要一个事务管理器,但在某些情况下,您可能需要在单个应用程序中使用多个独立的事务管理器 . @Transactional注释的value属性可用于选择性地指定要使用的PlatformTransactionManager的标识 . 这可以是bean名称或事务管理器bean的限定符值 . 例如,使用限定符表示法,以下Java代码

  • 1

    尝试使用 chained TransactionalManager

    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.transaction.ChainedTransactionManager;
    import org.springframework.transaction.PlatformTransactionManager;
    
    @Configuration
    public class ChainedDBConfig {
    
        @Bean("chainedTransactionManager")
        public PlatformTransactionManager transactionManager(
                @Qualifier("database1TransactionManager") final PlatformTransactionManager db1PlatformTransactionManager,
                @Qualifier("database2TransactionManager") final PlatformTransactionManager db2PlatformTransactionManager) {
    
            return new ChainedTransactionManager(db1PlatformTransactionManager, db2PlatformTransactionManager);
        }
    
    }
    

    并在服务类上放置以下注释:

    @Transactional(transactionManager = "chainedTransactionManager")
    public class AggregateMessagesJobIntegrationTest {
       ...
    }
    

    您也可以在集成测试中使用它:

    @RunWith(SpringRunner.class)
    @Transactional(transactionManager = "chainedRawAndAggregatedTransactionManager")
    @Rollback
    public class ExampleIntegrationTest extends AbstractIntegrationTest {
        ....
    }
    

    它将为两个数据库事务管理器执行回滚 .

相关问题