如何配置事务管理以在Spring中使用2个不同的db?

Rom*_*man 35 java spring jpa transactions multiple-databases

我有2个数据库(MySql和HSQLDB).我配置了2个数据源和2个EntityManagerFactory bean.我还可以配置2个对应的JpaTransactionManager bean.

但我不知道如何指定应该使用哪些来管理具体服务类的事务.我想@Transactional为此目的使用注释,但实际上我只能指定一个txManagers:

<tx:annotation-driven transaction-manager="manager"/>
Run Code Online (Sandbox Code Playgroud)

这种情况的出路是什么?

axt*_*avt 19

声明你的<tx:annotation-driven>没有事务管理器属性,为事务管理声明限定符,如下所示:

<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    <qualifier value="txManager1"/>
</bean>
Run Code Online (Sandbox Code Playgroud)

@Transactional中使用此限定符作为来选择一个事务管理器:

@Transactional("txManager1")
Run Code Online (Sandbox Code Playgroud)

或者,有更多属性:

@Transactional(value = "txManager1", readOnly = true)   
Run Code Online (Sandbox Code Playgroud)


ska*_*man 18

JpaTransactionManagerjavadoc对此有一些建议:

此事务管理器适用于使用单个JPA EntityManagerFactory进行事务数据访问的应用程序.JTA(通常通过JtaTransactionManager)是访问同一事务中的多个事务资源所必需的.请注意,您需要相应地配置JPA提供程序,以使其参与JTA事务.

换句话说,如果您发现自己有多个实体经理,并且有相应的tx经理,那么您应该考虑使用单个经理JtaTransactionManager.实体经理应该能够参与JTA交易,这将为您提供跨两个实体经理的完整交易,而不必担心您在任何时候都在哪个实体经理.

当然,JtaTransactionManager确实需要一个完整的支持JTA的应用服务器,而不是像Tomcat这样的vanilla servlet引擎.

  • 它并不那么简单.Spring TX管理器只是其他现有机制的包装,例如JTA,JPA/Hibernate或JDBC事务.JTA不依赖于一个数据库,它是一个分布式多数据库tx管理器.使用Spring并没有真正改变底层机制应该如何使用,它只是让它变得更容易. (3认同)

rak*_*sja 12

自从经过长时间的正确答案以来.

就多个数据库的JpaTransactionManager的可用性而言,Skaffman可能是正确的.

但是有一个工作解决方案可以使用2个不同的数据库和2个不同的JpaTransactionManager.

  @Bean(name = "db2TransactionManager")
  public PlatformTransactionManager transactionManager2() throws NamingException {
    JpaTransactionManager txManager = new JpaTransactionManager(entityManagerFactory());
    return txManager;
  }

  @Bean
  @Primary
  public PlatformTransactionManager transactionManager() throws Exception {
     JpaTransactionManager txManager = new JpaTransactionManager(entityManagerFactory());
    txManager.setNestedTransactionAllowed(true);
    return txManager;
  }
Run Code Online (Sandbox Code Playgroud)

@Primary 应该用于指定未指定限定符名称的那些 @Transactional


Mit*_*ani 6

您必须在application-context.xml中为其指定两个事务管理器,如下所示:

<tx:annotation-driven transaction-manager="manager1"/>
<tx:annotation-driven transaction-manager="manager2"/>
Run Code Online (Sandbox Code Playgroud)

@Transactional属性现在将使用其相关的事务管理器.

  • 有趣的是,如果我看一下处理`tx:annotation-driven`的`AnnotationDrivenBeanDefinitionParser`,则每个上下文只执行一次!所以第二行完全没用. (2认同)