我有2个数据库(MySql和HSQLDB)。我配置了2个数据源和2个EntityManagerFactory bean。我还可以配置2个对应的JpaTransactionManager bean。
但我不知道如何指定应该使用哪些来管理具体服务类的事务。我想为此目的使用@Transactional
注释,但实际上我只能指定一个txManagers:
<tx:annotation-driven transaction-manager="manager"/>
出现这种情况的方法是什么?
答案 0 :(得分:19)
声明您的<tx:annotation-driven>
没有事务管理器属性,为事务管理器声明限定符,如下所示:
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<qualifier value="txManager1"/>
</bean>
在 @Transactional 中使用此限定符作为值以选择一个事务管理器:
@Transactional("txManager1")
或者,有更多属性:
@Transactional(value = "txManager1", readOnly = true)
答案 1 :(得分:17)
javadoc for JpaTransactionManager对此有一些建议:
这个交易经理是 适合使用的应用程序 一个JPA EntityManagerFactory for 交易数据访问。 JTA (通常是通过 JtaTransactionManager)是必要的 用于访问多个事务 同一交易中的资源。 请注意,您需要配置您的 相应的JPA提供商为了 让它参加JTA 交易。
换句话说,如果您发现自己有多个实体经理,并且有相应的tx经理,那么您应该考虑使用单个JtaTransactionManager
。实体经理应该能够参与JTA交易,这将为您提供跨两个实体经理的完全交易,而不必担心您在任何时候都在哪个实体经理。
当然,JtaTransactionManager
确实需要一个完整的支持JTA的应用服务器,而不是像Tomcat这样的vanilla servlet引擎。
答案 2 :(得分:11)
自从经过长时间的正确回答以后。
Skaffman在JpaTransactionManager对多个数据库的可用性方面可能是正确的。
但是有一个工作解决方案可以使用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;
}
@Primary
应该用于指定@Transactional
答案 3 :(得分:6)
您必须在application-context.xml中为其指定两个事务管理器,如下所示:
<tx:annotation-driven transaction-manager="manager1"/>
<tx:annotation-driven transaction-manager="manager2"/>
@Transactional属性现在将使用其相关的事务管理器。