背景:项目中使用了两个mysql数据源,有一个功能是同时修改两个库里的表数据,需要进行事务控制。项目框架为springcloud+mybatis。
项目结构如下
增加maven依赖
<!--分布式事务支持--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jta-atomikos</artifactId> </dependency> <!--lombok jar 自动get set--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
application.properties
#carinfo spring.datasource.carinfo.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.carinfo.driverClassName=com.mysql.jdbc.Driver spring.datasource.carinfo.url=xxx spring.datasource.carinfo.username=xxx spring.datasource.carinfo.password=xxx spring.datasource.carinfo.maxActive=200 spring.datasource.carinfo.minIdle=2 spring.datasource.carinfo.initialSize=5 spring.datasource.carinfo.maxWait=60000 spring.datasource.carinfo.timeBetweenEvictionRunsMillis=60000 spring.datasource.carinfo.minEvictableIdleTimeMillis=300000 spring.datasource.carinfo.validationQuery=SELECT 1 FROM DUAL spring.datasource.carinfo.testWhileIdle=true spring.datasource.carinfo.testOnBorrow=false spring.datasource.carinfo.testOnReturn=false spring.datasource.carinfo.poolPreparedStatements=true spring.datasource.carinfo.maxPoolPreparedStatementPerConnectionSize=20 spring.datasource.carinfo.filters=stat spring.datasource.carinfo.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 #emscartype spring.datasource.emscartype.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.emscartype.driverClassName=com.mysql.jdbc.Driver spring.datasource.emscartype.url=xx spring.datasource.emscartype.username=xx spring.datasource.emscartype.password=xx spring.datasource.emscartype.maxActive=200 spring.datasource.emscartype.minIdle=2 spring.datasource.emscartype.initialSize=5 spring.datasource.emscartype.maxWait=60000 spring.datasource.emscartype.timeBetweenEvictionRunsMillis=60000 spring.datasource.emscartype.minEvictableIdleTimeMillis=300000 spring.datasource.emscartype.validationQuery=SELECT 1 FROM DUAL spring.datasource.emscartype.testWhileIdle=true spring.datasource.emscartype.testOnBorrow=false spring.datasource.emscartype.testOnReturn=false spring.datasource.emscartype.poolPreparedStatements=true spring.datasource.emscartype.maxPoolPreparedStatementPerConnectionSize=20 spring.datasource.emscartype.filters=stat spring.datasource.emscartype.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
DataSourceCarInfoProperties.java
package com.chinaway.ems.config.db; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * @Description: * @ClassName: DataSourceCarInfoProperties * @Author: Liu FangWei * @Date: 2018/11/8 9:55 * @Version: 1.0 */ @Component //自动注入 @ConfigurationProperties(prefix = "spring.datasource.carinfo") @Data // lombok注解,生成getter/setter等方法 public class DataSourceCarInfoProperties { private String type; private String driverClassName; private String url; private String username; private String password; private int minIdle; private int maxActive; private int maxWait; private String filters; private String connectionProperties; }
DataSourceEmsCarTypeProperties.java
package com.chinaway.ems.config.db; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * @Description: * @ClassName: DataSourceCarInfoProperties * @Author: Liu FangWei * @Date: 2018/11/8 9:55 * @Version: 1.0 */ @Component //自动注入 @ConfigurationProperties(prefix = "spring.datasource.emscartype") @Data // lombok注解,生成getter/setter等方法 public class DataSourceEmsCarTypeProperties { private String type; private String driverClassName; private String url; private String username; private String password; private int minIdle; private int maxActive; private int maxWait; private String filters; private String connectionProperties; }
DataSourceCarInfoConfig.java
package com.chinaway.ems.config.db; import javax.sql.DataSource; import com.alibaba.druid.pool.xa.DruidXADataSource; 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.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; 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; /** * @Description: * @ClassName: DataSourceCarInfoConfig * @Author: Liu FangWei * @Date: 2018/10/8 14:24 * @Version: 1.0 */ @Configuration @MapperScan(basePackages = {"com.chinaway.ems.dao.carinfo"}, sqlSessionTemplateRef = "sqlSessionTemplateCarInfo") public class DataSourceCarInfoConfig { @Bean(name = "dataSourceCarInfo") public DataSource dataSourceCarInfo(DataSourceCarInfoProperties dataSourceCarInfoProperties) { DruidXADataSource dataSource = new DruidXADataSource(); BeanUtils.copyProperties(dataSourceCarInfoProperties, dataSource); AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean(); xaDataSource.setXaDataSource(dataSource); xaDataSource.setUniqueResourceName("dataSourceCarInfo"); return xaDataSource; } @Bean(name = "sqlSessionFactoryCarInfo") public SqlSessionFactory sqlSessionFactoryCarInfo(@Qualifier("dataSourceCarInfo") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setTypeAliasesPackage("com.chinaway.ems.domain.carinfo"); //bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/car/*Mapper.xml")); return bean.getObject(); } @Bean(name = "sqlSessionTemplateCarInfo") public SqlSessionTemplate sqlSessionTemplateCarInfo( @Qualifier("sqlSessionFactoryCarInfo") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
DataSourceEmsCarTypeConfig.java
package com.chinaway.ems.config.db; import com.alibaba.druid.pool.xa.DruidXADataSource; 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.BeanUtils; import org.springframework.beans.factory.annotation.Qualifier; 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 javax.sql.DataSource; /** * @Description: * @ClassName: DataSourceEmsCarTypeConfig * @Author: Liu FangWei * @Date: 2018/10/8 14:24 * @Version: 1.0 */ @Configuration @MapperScan(basePackages = {"com.chinaway.ems.dao.emscartype"}, sqlSessionTemplateRef = "sqlSessionTemplateEmsCarType") public class DataSourceEmsCarTypeConfig { @Primary @Bean(name = "dataSourceEmsCarType") public DataSource dataSourceEmsCarType(DataSourceEmsCarTypeProperties dataSourceEmsCarTypeProperties) { DruidXADataSource dataSource = new DruidXADataSource(); BeanUtils.copyProperties(dataSourceEmsCarTypeProperties, dataSource); AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean(); xaDataSource.setXaDataSource(dataSource); xaDataSource.setUniqueResourceName("dataSourceEmsCarType"); return xaDataSource; } @Bean(name = "sqlSessionFactoryEmsCarType") public SqlSessionFactory sqlSessionFactoryEmsCarType(@Qualifier("dataSourceEmsCarType") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setTypeAliasesPackage("com.chinaway.ems.domain.emscartype"); //bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/car/*Mapper.xml")); return bean.getObject(); } @Bean(name = "sqlSessionTemplateEmsCarType") public SqlSessionTemplate sqlSessionTemplateEmsCarType( @Qualifier("sqlSessionFactoryEmsCarType") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
XATransactionManagerConfig.java
package com.chinaway.ems.config.db; import com.atomikos.icatch.jta.UserTransactionImp; import com.atomikos.icatch.jta.UserTransactionManager; import org.springframework.context.annotation.Bean; 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 javax.transaction.TransactionManager; import javax.transaction.UserTransaction; /** * @Description: * @ClassName: XATransactionManagerConfig * @Author: Liu FangWei * @Date: 2018/11/8 10:24 * @Version: 1.0 */ @Configuration @EnableTransactionManagement public class XATransactionManagerConfig { @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 { return new JtaTransactionManager(userTransaction(), atomikosTransactionManager()); } }
为了控制atomikos的日志输出目录,增加transactions.properties
com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory com.atomikos.icatch.log_base_dir=translogs com.atomikos.icatch.console_file_name=tm.out com.atomikos.icatch.log_base_name=tmlog com.atomikos.icatch.tm_unique_name=com.tlw.bpm.engine.atomikos.spring.jdbc.tm com.atomikos.icatch.console_file_limit=10000 com.atomikos.icatch.console_file_count=10 com.atomikos.icatch.max_timeout=600000 com.atomikos.icatch.default_jta_timeout=120000 com.atomikos.icatch.console_log_level=ERROR com.atomikos.icatch.enable_logging=false
因为atomikos频繁的输出日志,项目中用的log4j2,通过配置log4j2.xml让atomikos只打印warn级别以上的日志
<Logger name="com.atomikos" level="WARN" additivity="true"> <AppenderRef ref="AsyncAppender"/> <AppenderRef ref="Console"/> </Logger>
通过以上配置就可以实现jta了,记得在调用的service方法上加上@Transactional注解哦。
相关推荐
Spring Boot 支持 JTA,可以通过其集成的 `Atomikos` 或 `Bitronix` 事务管理器实现分布式事务。 `MyBatis` 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码...
本文将详细讲解"springboot-jpa atomikos 分布式事务管理"这一主题,以及如何在SpringBoot 2.0.5版本中结合JPA、Hibernate和MyBatis实现多数据库事务控制。 首先,SpringBoot是一个简化Spring应用开发的框架,它...
Spring Boot:mybatis-plus + atomikos + druid 实现不同实例数据库的多数据源配置和分布式事务管理(demo项目),想到工作上可能会用到多数据源,但是自己在这方面并不是很熟悉,于是在网上查阅了很多文章,结果...
《SpringBoot、MyBatis与Atomikos整合实现两阶段提交分布式事务》 在现代企业级应用中,尤其是在微服务架构下,分布式事务处理成为了一项挑战。本项目"springboot-mybatis-atomikos.zip"正是为了解决这一问题而设计...
然后,Atomikos 是一个开源的 JTA(Java Transaction API)实现,它支持分布式事务管理。在分布式系统中,当多个微服务或组件涉及到跨数据库的操作时,Atomikos 能够确保这些操作要么全部成功,要么全部回滚,遵循 ...
本篇文档主要讲述如何使用Spring Boot结合MyBatis、JTA(Java Transaction API)以及Atomikos实现多数据源的事务管理。 ### Spring Boot框架 Spring Boot是Spring家族中的一个全新框架,用于简化新Spring应用的...
SpringBoot集成Atomikos使用Oracle数据库mybatisSpringBoot集成Atomikos使用Oracle数据库mybatisSpringBoot集成Atomikos使用Oracle数据库mybatisSpringBoot集成Atomikos使用Oracle数据库mybatis
在本项目中,我们主要探讨的是如何利用Spring Boot、MyBatis、Druid、Atomikos、WebSocket、Redis以及Swagger2构建一个具有多数据源、分布式事务管理,并且集成了实时通信与API文档管理功能的高级应用。下面将对这些...
本教程将详细讲解如何使用Spring Boot、Druid和Mybatis来实现JTA(Java Transaction API)分布式事务。这是一项高级技术,它允许在多数据库环境或者微服务架构中进行一致性的数据操作。 首先,让我们了解什么是JTA...
本文将详细讲解如何利用Spring Boot、Atomikos、JPA(Java Persistence API)以及MySQL来实现JTA(Java Transaction API)分布式事务。 首先,Spring Boot是一个轻量级的框架,它简化了基于Spring的应用程序开发...
通常,我们可以使用`JtaTransactionManager`配合Atomikos、Bitronix等JTA实现来处理分布式事务。以下是一个简单的示例: ```java @Configuration @EnableTransactionManagement public class TransactionConfig { ...
本教程将探讨如何利用Spring Boot、Druid、Mybatis以及Atomikos来配置多数据源并实现分布式事务。 首先,Spring Boot是Java生态系统中的一个流行框架,它简化了设置和配置过程,使得开发人员可以快速启动新项目。在...
本案例主要探讨如何利用Spring Boot、Atomikos、JTA(Java Transaction API)、Hibernate以及MyBatis,结合MySQL数据库,实现一个跨数据源的分布式事务解决方案。 首先,Spring Boot是一个基于Spring框架的快速开发...
atomikos是一款开源的事务处理中间件,它实现了JTA(Java Transaction API)和JTS(Java Transaction Service),用于处理分布式事务。在多数据源环境下,atomikos能够保证跨数据源操作的一致性和原子性,确保事务的...
springboot该项目是基于springboot进行配置,包括了数据库配置,aop配置,多数据库和分布式事务配置数据库配置:jdbc,jpa,mybatis(注解和mapper文件)mvn mybatis-generator:generate 代码生成器配置多数据库的配置,...
spring+mybatis+atomikos,java分布式事务。 由于网上的多数据源事务的帖子大多是2010年以前的,现在spring都已经到4.X了,有些类已经弃用了。 原先很多都是用jotm实现的,但是由于spring的升级,totm的本地化实例...
实现单表业务零SQL集成Atomikos支持分布式事务,以及支持多数据源配置统一异常处理统一响应结果封装基于JWT实现基于Token的鉴权机制使用Druid Spring Boot Starter集成Druid数据库连接池与监控使用AutoGenerator快速...
SpringBoot支持分布式事务管理,如Atomikos、Bitronix等,确保数据一致性。 7. **前端界面**:可能使用Thymeleaf、Freemarker等模板引擎配合HTML、CSS和JavaScript来构建用户友好的交互界面,实现动态数据展示和...
SpringBoot可以通过集成分布式事务管理器如Atomikos来实现分布式事务,但出于性能考虑,通常会采用基于补偿的事务管理策略,如两阶段提交(2PC)或Saga模式,利用消息系统来确保事务的一致性。 至于Shiro、OAuth和...