使用AbstractRoutingDataSource
配置多个 SqlSessionFactory
前言
粗俗的阅读了一下spring的源码,由于 spring 事务的机制,在开启事务之前spring 会去创建当前数据源的 事务object,直到事务提交,spring 都不会在乎你是否切换了数据源。这就导致了,使用 AbstractRouting DataSource 方式开启事务时,切换数据源不生效。
关于如何解决这个问题,感兴趣的朋友可以去阅读一下:https://www.jianshu.com/p/61e8961c6154
本文只讨论上述第二种方式结合 atomikos 管理多数据源事务。
Atomikos
来自:http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-jta.html
Atomikos is a popular open source transaction manager which can be embedded into your Spring Boot application. You can use the
spring-boot-starter-jta-atomikos
Starter to pull in the appropriate Atomikos libraries. Spring Boot auto-configures Atomikos and ensures that appropriatedepends-on
settings are applied to your Spring beans for correct startup and shutdown ordering.
By default, Atomikos transaction logs are written to a
transaction-logs
directory in your application’s home directory (the directory in which your application jar file resides). You can customize the location of this directory by setting aspring.jta.log-dir
property in yourapplication.properties
file. Properties starting withspring.jta.atomikos.properties
can also be used to customize the AtomikosUserTransactionServiceImp
. See theAtomikosProperties
Javadoc for complete details.
引入spring-boot-starter-jta-atomikos,spring boot 为我们自动配置
Atomikos,我们可以通过 spring.jta.xxx
修改默认配置。
Talk is cheap. Show me the code
demo源码:https://gitee.com/yintianwen7/taven-springboot-learning/tree/master/spring-atomikos
添加 maven 依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jta-atomikos</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency>
application.properties
#spring.jta.log-dir=classpath:tx-logsspring.jta.transaction-manager-id=txManager spring.datasource.druid.system-db.name=system-db spring.datasource.druid.system-db.url=jdbc:mysql://localhost:3306/test1?useSSL=falsespring.datasource.druid.system-db.username=root spring.datasource.druid.system-db.password=taven753 spring.datasource.druid.system-db.initialSize=5 spring.datasource.druid.system-db.minIdle=5 spring.datasource.druid.system-db.maxActive=20 spring.datasource.druid.system-db.maxWait=60000 spring.datasource.druid.system-db.timeBetweenEvictionRunsMillis=60000 spring.datasource.druid.system-db.minEvictableIdleTimeMillis=30000 spring.datasource.druid.system-db.validationQuery=SELECT 1 spring.datasource.druid.system-db.validationQueryTimeout=10000 spring.datasource.druid.system-db.testWhileIdle=truespring.datasource.druid.system-db.testOnBorrow=falsespring.datasource.druid.system-db.testOnReturn=falsespring.datasource.druid.system-db.poolPreparedStatements=truespring.datasource.druid.system-db.maxPoolPreparedStatementPerConnectionSize=20 spring.datasource.druid.system-db.filters=stat,wall spring.datasource.druid.system-db.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 spring.datasource.druid.system-db.useGlobalDataSourceStat=truespring.datasource.druid.business-db.name=business-db spring.datasource.druid.business-db.url=jdbc:mysql://localhost:3306/test2?useSSL=falsespring.datasource.druid.business-db.username=root spring.datasource.druid.business-db.password=taven753 spring.datasource.druid.business-db.initialSize=5 spring.datasource.druid.business-db.minIdle=5 spring.datasource.druid.business-db.maxActive=20 spring.datasource.druid.business-db.maxWait=60000 spring.datasource.druid.business-db.timeBetweenEvictionRunsMillis=60000 spring.datasource.druid.business-db.minEvictableIdleTimeMillis=30000 spring.datasource.druid.business-db.validationQuery=SELECT 1 spring.datasource.druid.business-db.validationQueryTimeout=10000 spring.datasource.druid.business-db.testWhileIdle=truespring.datasource.druid.business-db.testOnBorrow=falsespring.datasource.druid.business-db.testOnReturn=falsespring.datasource.druid.business-db.poolPreparedStatements=truespring.datasource.druid.business-db.maxPoolPreparedStatementPerConnectionSize=20 spring.datasource.druid.business-db.filters=stat,wall spring.datasource.druid.business-db.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 spring.datasource.druid.business-db.useGlobalDataSourceStat=true
system 数据源的配置类
import javax.sql.DataSource;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.annotation.MapperScan;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import com.gitee.taven.config.prop.SystemProperties;import com.gitee.taven.utils.PojoUtil;@Configuration@MapperScan(basePackages = SystemDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "systemSqlSessionFactory")public class SystemDataSourceConfig { static final String PACKAGE = "com.gitee.taven.mapper.system"; @Autowired private SystemProperties systemProperties; @Bean(name = "systemDataSource") @Primary public DataSource systemDataSource() { AtomikosDataSourceBean ds = new AtomikosDataSourceBean(); ds.setXaProperties(PojoUtil.obj2Properties(systemProperties)); ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource"); ds.setUniqueResourceName("systemDataSource"); ds.setPoolSize(5); return ds; } @Bean @Primary public SqlSessionFactory systemSqlSessionFactory() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(systemDataSource()); return sqlSessionFactoryBean.getObject(); } }
business 数据源的配置类同上
省略了 mybatis 代码,通过service 测试事务,抛出异常后,事务会回滚
@Servicepublic class UserService { @Autowired private UsersMapper usersMapper; @Autowired private UserInformationsMapper userInformationsMapper; @Transactional public void testJTA() { Users u = new Users(); u.setUsername("hmj"); u.setPassword("hmjbest"); usersMapper.insertSelective(u); UserInformations ui = new UserInformations(); ui.setUserid(666l); ui.setEmail("dsb"); userInformationsMapper.insertSelective(ui); // int i = 10/0; } }
作者:殷天文
链接:https://www.jianshu.com/p/f9bac5822d30
共同学习,写下你的评论
评论加载中...
作者其他优质文章