(十二)Spring Boot+Druid+Mybatis实现JTA分布式事务
2017-08-28 10:14
633 查看
源码下载:点此下载 整合Mybatis 配置两个SqlSessionFactory 分别扫描不同的包
对于分布式事务而言, JTA 是一个不错的解决方案,通常 JTA 需要应用服务器的支持,但在查阅 SpringBoot 的文档时发现,它推荐了 Atomikos 和 Bitronix 两种无需服务器支持的分布式事务组件,在这两个组件中, Atomikos 更受大家的好评,所以我选择使用它.
然后要配置JTA事务管理
对于分布式事务而言, JTA 是一个不错的解决方案,通常 JTA 需要应用服务器的支持,但在查阅 SpringBoot 的文档时发现,它推荐了 Atomikos 和 Bitronix 两种无需服务器支持的分布式事务组件,在这两个组件中, Atomikos 更受大家的好评,所以我选择使用它.
引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jta-atomikos</artifactId> </dependency>
application.properties
#配置jdbc数据源 #配置多数据源 #数据源名称(与下列配置的数据源对应,多个数据源要配多个名称) jdbc.datasources=ds,ds1 jdbc.ds.driverClassName=com.mysql.jdbc.Driver jdbc.ds.url=jdbc\:mysql\://localhost\:3306/ryx?characterEncoding\=UTF-8&pinGlobalTxToPhysicalConnection\=true jdbc.ds.username=root jdbc.ds.password=123456 jdbc.ds1.driverClassName=com.mysql.jdbc.Driver jdbc.ds1.url=jdbc\:mysql\://172.20.1.5\:3306/ryx?characterEncoding\=UTF-8&pinGlobalTxToPhysicalConnection\=true jdbc.ds1.username=root jdbc.ds1.password=root #druid监控平台账号密码 druid.username=root druid.password=Ruyixing2017注意:使用Druid配置JTA事务需要使用DruidXADataSource,不要再使用DruidDataSource了
TestMyBatisConfig.java
package com.test.springboot.config.datasource; import java.sql.SQLException; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.xa.DruidXADataSource; import com.atomikos.jdbc.AtomikosDataSourceBean; import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource; @Configuration // basePackages 最好分开配置 如果放在同一个文件夹可能会报错 @MapperScan(basePackages = "com.test.springboot.dao", sqlSessionTemplateRef = "testSqlSessionTemplate") public class TestMyBatisConfig { @Value("${jdbc.ds.driverClassName}") private String driver; @Value("${jdbc.ds.url}") private String url; @Value("${jdbc.ds.username}") private String username; @Value("${jdbc.ds.password}") private String password; // 配置数据源 @Primary @Bean(name = "testDataSource",initMethod="init",destroyMethod="close") public DataSource dataSource() throws SQLException{ DruidXADataSource dataSource=new DruidXADataSource(); //DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); //配置最大连接 dataSource.setMaxActive(300); //配置初始连接 dataSource.setInitialSize(20); //配置最小连接 dataSource.setMinIdle(10); //连接等待超时时间 dataSource.setMaxWait(60000); //间隔多久进行检测,关闭空闲连接 dataSource.setTimeBetweenEvictionRunsMillis(60000); //一个连接最小生存时间 dataSource.setMinEvictableIdleTimeMillis(300000); //连接等待超时时间 单位为毫秒 缺省启用公平锁, //并发效率会有所下降, 如果需要可以通过配置useUnfairLock属性为true使用非公平锁 dataSource.setUseUnfairLock(true); //用来检测是否有效的sql dataSource.setValidationQuery("select 'x'"); dataSource.setTestWhileIdle(true); //申请连接时执行validationQuery检测连接是否有效,配置为true会降低性能 dataSource.setTestOnBorrow(false); //归还连接时执行validationQuery检测连接是否有效,配置为true会降低性能 dataSource.setTestOnReturn(false); //打开PSCache,并指定每个连接的PSCache大小启用poolPreparedStatements后, //PreparedStatements 和CallableStatements 都会被缓存起来复用, //即相同逻辑的SQL可以复用一个游标,这样可以减少创建游标的数量。 dataSource.setPoolPreparedStatements(true); dataSource.setMaxOpenPreparedStatements(20); //配置sql监控的filter dataSource.setFilters("stat,wall,log4j"); try { dataSource.init(); } catch (SQLException e) { e.printStackTrace(); } AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean(); xaDataSource.setXaDataSource(dataSource); xaDataSource.setUniqueResourceName("testDataSource"); /*xaDataSource.setMinPoolSize(10); xaDataSource.setMaxPoolSize(300); xaDataSource.setMaxLifetime(20000); xaDataSource.setBorrowConnectionTimeout(30); xaDataSource.setLoginTimeout(30); xaDataSource.setMaintenanceInterval(60); xaDataSource.setMaxIdleTime(60); xaDataSource.setTestQuery("select 'x'");*/ return xaDataSource; } @Bean(name = "testSqlSessionFactory") public SqlSessionFactory testSqlSessionFactory(@Qualifier("testDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); //bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/test/springboot/dao/*.xml")); return bean.getObject(); } @Bean(name = "testSqlSessionTemplate") public SqlSessionTemplate testSqlSessionTemplate( @Qualifier("testSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
Test2MyBatisConfig.java
package com.test.springboot.config.datasource; import java.sql.SQLException; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.xa.DruidXADataSource; import com.atomikos.jdbc.AtomikosDataSourceBean; import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource; @Configuration @MapperScan(basePackages = "com.test.springboot.dao2", sqlSessionTemplateRef = "test2SqlSessionTemplate") public class Test2MyBatisConfig { @Value("${jdbc.ds1.driverClassName}") private String driver; @Value("${jdbc.ds1.url}") private String url; @Value("${jdbc.ds1.username}") private String username; @Value("${jdbc.ds1.password}") private String password; @Bean(name = "test2DataSource",initMethod="init",destroyMethod="close") public DataSource dataSource() throws SQLException{ DruidXADataSource dataSource=new DruidXADataSource(); //DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); //配置最大连接 dataSource.setMaxActive(300); //配置初始连接 dataSource.setInitialSize(20); //配置最小连接 dataSource.setMinIdle(10); //连接等待超时时间 dataSource.setMaxWait(60000); //间隔多久进行检测,关闭空闲连接 dataSource.setTimeBetweenEvictionRunsMillis(60000); //一个连接最小生存时间 dataSource.setMinEvictableIdleTimeMillis(300000); //连接等待超时时间 单位为毫秒 缺省启用公平锁, //并发效率会有所下降, 如果需要可以通过配置useUnfairLock属性为true使用非公平锁 dataSource.setUseUnfairLock(true); //用来检测是否有效的sql dataSource.setValidationQuery("select 'x'"); dataSource.setTestWhileIdle(true); //申请连接时执行validationQuery检测连接是否有效,配置为true会降低性能 dataSource.setTestOnBorrow(false); //归还连接时执行validationQuery检测连接是否有效,配置为true会降低性能 dataSource.setTestOnReturn(false); //打开PSCache,并指定每个连接的PSCache大小启用poolPreparedStatements后, //PreparedStatements 和CallableStatements 都会被缓存起来复用, //即相同逻辑的SQL可以复用一个游标,这样可以减少创建游标的数量。 dataSource.setPoolPreparedStatements(true); dataSource.setMaxOpenPreparedStatements(20); //配置sql监控的filter dataSource.setFilters("stat,wall,log4j"); try { dataSource.init(); } catch (SQLException e) { e.printStackTrace(); } AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean(); xaDataSource.setXaDataSource(dataSource); xaDataSource.setUniqueResourceName("test2DataSource"); /*xaDataSource.setMinPoolSize(10); xaDataSource.setMaxPoolSize(300); xaDataSource.setMaxLifetime(20000); xaDataSource.setBorrowConnectionTimeout(30); xaDataSource.setLoginTimeout(30); xaDataSource.setMaintenanceInterval(60); xaDataSource.setMaxIdleTime(60); xaDataSource.setTestQuery("select 'x'");*/ return xaDataSource; } @Bean(name = "test2SqlSessionFactory") public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); //bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/test/springboot/dao2/*.xml")); return bean.getObject(); } @Bean(name = "test2SqlSessionTemplate") public SqlSessionTemplate testSqlSessionTemplate( @Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
然后要配置JTA事务管理
TransactionManagerConfig.java
package com.test.springboot.config.datasource; import javax.transaction.TransactionManager; import javax.transaction.UserTransaction; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.jta.JtaTransactionManager; import com.atomikos.icatch.jta.UserTransactionImp; import com.atomikos.icatch.jta.UserTransactionManager; @Configuration @ComponentScan @EnableTransactionManagement public class TransactionManagerConfig { @Bean(name = "userTransaction") public UserTransaction userTransaction() throws Throwable { UserTransactionImp userTransactionImp = new UserTransactionImp(); userTransactionImp.setTransactionTimeout(10000); return userTransactionImp; } @Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close") public TransactionManager atomikosTransactionManager() throws Throwable { UserTransactionManager userTransactionManager = new UserTransactionManager(); userTransactionManager.setForceShutdown(false); return userTransactionManager; } @Bean(name = "transactionManager") @DependsOn({ "userTransaction", "atomikosTransactionManager" }) public PlatformTransactionManager transactionManager() throws Throwable { UserTransaction userTransaction = userTransaction(); JtaTransactionManager manager = new JtaTransactionManager(userTransaction,atomikosTransactionManager()); return manager; } }
测试方法
在需要事务的service方法内注入两个数据库的操作对应的mapper,然后在方法上标注@Transactional注解就可以了,跟之前使用方法没什么两样@Override @Transactional public Integer insetStudent(Student student) { Integer integer = studentMapper.insetStudent(student); Integer integer2 = studentMapper2.insetStudent(student); int a=10/0; return integer; }
相关文章推荐
- Spring Boot 整合 Mybatis 实现 Druid 多数据源
- Spring Boot 整合 Mybatis 实现 Druid 多数据源详解
- Springboot整合Mybatis实现Druid多数据源
- (十一)Spring Boot整合Mybatis使用druid实现多数据源自动切换
- spring boot+mvc+mybatis(通用mapper)+druid+jsp+bootstrap实现后台权限管理系统源码
- Spring Boot 整合 Mybatis 实现 Druid 多数据源详解
- Spring Boot 整合 Mybatis 实现 Druid 多数据源详解
- 详解Spring Boot整合Mybatis实现 Druid多数据源配置
- Springboot+Mybatis+Druid 实现多数据源,与事务管理
- SpringBoot+Mybatis+ Druid+PageHelper 实现多数据源并分页
- Spring Boot 整合 Mybatis 实现 Druid 多数据源详解
- Spring Boot+Mybatis+Druid+PageHelper实现多数据源并分页的方法
- Spring Boot 整合 Mybatis 实现 Druid 多数据源详解
- Spring Boot 整合 Mybatis 实现 Druid 多数据源详解
- 运用springboot+mybatis 实现动态多数据源
- Druid简介(Spring Boot + Mybatis + Druid数据源【官方start】)
- spring boot + mybatis + druid + redis
- 详细步骤!!!idea+springboot+mybatis+jsp+bootstrap实现从mysql查询出数据并显示(源码)
- spring boot中使用druid多数据源配置Mybatis