老师,能帮我看一下吗?两个spring data jpa数据源共用一个jtaTransactionManager出问题啦~
来源:4-9 JTA多数据源事务实例

他门说这就是人生
2019-12-16
我想测试两个MySQL数据库的多数据源事务,配置了两个spring data jpa数据源。如下:
@Configuration @PropertySource({ "classpath:persistence-multiple-db.properties" }) @EnableJpaRepositories( basePackages = "com.gaojingsi.transaction.muiltidatasourcetransactiondemo.repository.db2", entityManagerFactoryRef = "db2EntityManager", transactionManagerRef = "jtaTransactionManager" ) public class Db2Config { @Autowired private Environment env; @Bean @Primary public LocalContainerEntityManagerFactoryBean db2EntityManager() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(db2DataSource()); em.setPackagesToScan( new String[] { "com.gaojingsi.transaction.muiltidatasourcetransactiondemo.entity.db2" }); HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); HashMap<String, Object> properties = new HashMap<>(); properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); properties.put("hibernate.dialect", env.getProperty("hibernate.dialect")); em.setJpaPropertyMap(properties); return em; } @Primary @Bean public DataSource db2DataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName( env.getProperty("db2.driver-class-name")); dataSource.setUrl(env.getProperty("db2.jdbc-url")); dataSource.setUsername(env.getProperty("db2.username")); dataSource.setPassword(env.getProperty("db2.password")); return dataSource; } // @Primary // @Bean // public PlatformTransactionManager db2TransactionManager() { // // JpaTransactionManager transactionManager // = new JpaTransactionManager(); // transactionManager.setEntityManagerFactory( // db2EntityManager().getObject()); // return transactionManager; // } }
@Configuration @PropertySource({ "classpath:persistence-multiple-db.properties" }) @EnableJpaRepositories( basePackages = "com.gaojingsi.transaction.muiltidatasourcetransactiondemo.repository.db1", entityManagerFactoryRef = "db1EntityManager", transactionManagerRef = "jtaTransactionManager" ) public class Db1Config { @Autowired private Environment env; @Bean public LocalContainerEntityManagerFactoryBean db1EntityManager() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(db1DataSource()); em.setPackagesToScan( new String[] { "com.gaojingsi.transaction.muiltidatasourcetransactiondemo.entity.db1" }); HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); HashMap<String, Object> properties = new HashMap<>(); properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); properties.put("hibernate.dialect", env.getProperty("hibernate.dialect")); em.setJpaPropertyMap(properties); return em; } @Bean public DataSource db1DataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName( env.getProperty("db1.driver-class-name")); dataSource.setUrl(env.getProperty("db1.jdbc-url")); dataSource.setUsername(env.getProperty("db1.username")); dataSource.setPassword(env.getProperty("db1.password")); return dataSource; } // @Bean // public PlatformTransactionManager db1TransactionManager() { // // JpaTransactionManager transactionManager // = new JpaTransactionManager(); // transactionManager.setEntityManagerFactory( // db1EntityManager().getObject()); // return transactionManager; // } }
还配置了一个公共的PlatformTransactionManager:
@Configuration @EnableTransactionManagement public class WebConfig implements WebMvcConfigurer { @Bean(name = "jtaTransactionManager") public PlatformTransactionManager jtaTransactionManager() { UserTransactionManager userTransactionManager = new UserTransactionManager(); UserTransaction userTransaction = new UserTransactionImp(); return new JtaTransactionManager(userTransaction, userTransactionManager); } }
如果在@EnableJpaRepositories的transactionManagerRef中,各用各的transactionManager,两个数据库都能成功插入数据,但没法保障两个数据库的事务。
所以我配置了一个jtaTransactionManager,希望两个数据源共用这个jtaTransactionManager,结果在没有异常和错误的情况下也只有一个数据库的操作生效。不知道如何测试两个MySQL数据库的事务,并保证一致性和原子性。
ps:
我的demo在gitee上:
https://gitee.com/feitianzouxiu/multi-datasource-transaction-demo.git
老师抽空帮我看看行吗?感激不尽呀~~~
写回答
1回答
-
首先,实在是抱歉,我前段时间一直出差,也比较忙,没有顾上看这个问题,我看到你问的几个多数据源的问题,我还给你回复了,结果你都自己解决了。还请见谅。
你试一下:
HashMap<String, Object> properties = new HashMap<String, Object>(); properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName()); properties.put("javax.persistence.transactionType", "JTA"); LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean(); entityManager.setJpaPropertyMap(properties);
如果还不行,那就是需要使用XADataSource,也就是`MysqlXADataSource`。
00
相似问题