【问题标题】:Multiple transaction managers annotation configuration多个事务管理器注解配置
【发布时间】:2012-08-06 12:44:11
【问题描述】:

我在基于注解的配置类中配置了两个事务管理器:

@Configuration
@EnableTransactionManagement
public class DBConfig implements TransactionManagementConfigurer {

//...

@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
    return defTransactionManager();
}

@Bean
@Qualifier("defSessionFactory")
public LocalSessionFactoryBean defSessionFactory() {
    LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
    sfb.setDataSource(defDataSource());

    Properties props = new Properties();
    //...

    sfb.setHibernateProperties(props);
    sfb.setPackagesToScan("my.package");

    return sfb;
}

@Bean
@Qualifier("defTransactionManager")
public PlatformTransactionManager defTransactionManager() {
    return new HibernateTransactionManager(defSessionFactory().getObject());
}

@Bean
@Qualifier("secondSessionFactory")
public LocalSessionFactoryBean secondSessionFactory() {
    LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
    sfb.setDataSource(secondDataSource());

    Properties props = new Properties();
    //...

    sfb.setHibernateProperties(props);
    sfb.setPackagesToScan("my.package.subpackage");

    return sfb;
}

@Bean
@Qualifier("secondTM")
public PlatformTransactionManager secondTransactionManager() {
    return new HibernateTransactionManager(secondSessionFactory().getObject());
}
}

我的意图是使用带有两个事务管理器的注释事务。 像这样注释的方法

@Transactional
public void method() {}

应该由defTransactionManager处理

以及像这样注释的方法

@Transactional("secondTM")
public void anotherMethod() {}

通过 secondTransactionManager

defTransactionManager 工作正常,但是当涉及到 anotherMethod() 我得到:

org.hibernate.HibernateException: No Session found for current thread

当我对另一个方法使用编程事务管理(自动连接 secondSessionFactory,使用 TransactionTemplate)时,一切正常。

【问题讨论】:

    标签: spring hibernate annotations config


    【解决方案1】:

    如果@EnableTranscationManagementSpring 将使用按类型查找,您可以将自己的查找方法提供给单个事务管理器,但it will not work for two tx managers

    如果你想检查 Spring 如何确定要执行的事务,你可以尝试调试 TransactionAspectSupport 类。关键方法是setTransactionManagerBeanNamedetermineTransactionManager

    【讨论】:

    • 我希望这是因为我的配置类实现了 TransactionManagementConfigurer 并且被覆盖的方法 annotationDrivenTransactionManager 返回 defTransactionManager()
    • @AlexanderCamperov 它是一个网络应用程序吗?
    • 您是否检查过@Transactional() 是否在您期望@Transactional("secondTM") 工作的完全相同的bean 上工作?
    • 我不能这样做,它们意味着要使用不同的数据源和不同的实体。实际上,在我开始将项目从 xml 配置迁移到注释配置之前,它们工作得很好。
    • 此外,@@Transactional 不起作用的 bean 实际上存在于未声明 AOP 拦截器的另一个上下文中,这种可能性很小。例如,如果您的事务配置在根应用程序上下文中工作,但 @@Transactional 注释是在 servlet 上下文 bean 上声明的 - 例如如果它们被自动扫描意外选中并在 servlet 上下文中创建。
    【解决方案2】:

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

    @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 注释并指定txManager@Transactional 注释中,例如

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

    【讨论】:

    • 我也有类似的问题。我可以使用两个事务管理器,但我的删除查询不起作用。
    猜你喜欢
    • 1970-01-01
    • 2012-12-14
    • 2014-05-22
    • 1970-01-01
    • 2017-07-30
    • 1970-01-01
    • 2011-05-08
    • 2011-03-20
    • 1970-01-01
    相关资源
    最近更新 更多