【Spring实战】springboot+Atomikos+mybatis+mysql 实现分布式事务

Danica ·
更新时间:2024-09-21
· 842 次阅读

1 环境

(1) 数据库
在这里插入图片描述

CREATE TABLE `t_student` ( `n_id` int(11) NOT NULL AUTO_INCREMENT, `c_name` varchar(255) DEFAULT NULL, `c_age` int(12) DEFAULT NULL, PRIMARY KEY (`n_id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; CREATE TABLE `t_teacher` ( `n_id` int(11) NOT NULL AUTO_INCREMENT, `c_name` varchar(255) DEFAULT NULL, PRIMARY KEY (`n_id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

(2) 工程
org.springframework.boot spring-boot-starter-web provided org.projectlombok lombok org.springframework.boot spring-boot-starter-test test junit junit 4.12 test org.apache.commons commons-lang3 org.mybatis.spring.boot mybatis-spring-boot-starter 1.3.1 tk.mybatis mapper-spring-boot-starter 2.1.5 com.github.pagehelper pagehelper-spring-boot-starter 1.2.10 mysql mysql-connector-java 5.1.47 com.alibaba druid 1.1.10 org.springframework.boot spring-boot-configuration-processor true org.springframework.boot spring-boot-starter-jta-atomikos 3 application.yml #配置端口 server: port: 8080 #配置数据源 spring: #student的配置 student: uniqueResourceName: studentDatasource jdbcUrl: jdbc:mysql://localhost:3306/db_student?characterEncoding=utf-8&useSSL=false username: root password: 123456 poolSize: 10 dataSourceClassName: com.mysql.jdbc.jdbc2.optional.MysqlXADataSource #teacher配置 teacher: uniqueResourceName: teacherDatasource jdbcUrl: jdbc:mysql://localhost:3306/db_teacher?characterEncoding=utf-8&useSSL=false username: root password: 123456 poolSize: 10 dataSourceClassName: com.mysql.jdbc.jdbc2.optional.MysqlXADataSource 4 student数据源配置 @ConfigurationProperties(prefix = "spring.student") @Data public class StudentDataSourceProperties { /** * 数据源唯一资源名 */ private String uniqueResourceName; /** * jdbc链接URL */ private String jdbcUrl; /** * 用户名 */ private String username; /** * 密码 */ private String password; /** * 连接池 */ private Integer poolSize; /** * 数据源类名 */ private String dataSourceClassName; } @Configuration @Import(StudentDataSourceProperties.class) @MapperScan(basePackages = "com.spring.student.mapper", sqlSessionFactoryRef = "studentSqlSessionFactory") public class StudentDatasourceConfig { @Autowired private StudentDataSourceProperties studentProperties; /** * 配置AtomikosDataSourceBean数据源 * */ @Bean(name = "studentDatasource") @Primary public DataSource studentDataSource() { //属性 Properties properties = new Properties(); properties.put("URL",studentProperties.getJdbcUrl()); properties.put("user", studentProperties.getUsername()); properties.put("password", studentProperties.getPassword()); //数据源 AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean(); atomikosDataSourceBean.setUniqueResourceName(studentProperties.getUniqueResourceName()); atomikosDataSourceBean.setXaDataSourceClassName(studentProperties.getDataSourceClassName()); atomikosDataSourceBean.setPoolSize(studentProperties.getPoolSize()); atomikosDataSourceBean.setXaProperties(properties); return atomikosDataSourceBean; } /** * 获取sqlSessionFactory */ @Bean public SqlSessionFactory studentSqlSessionFactory() throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(studentDataSource()); return factoryBean.getObject(); } /** * 获取会话模板 */ @Bean public SqlSessionTemplate studentSqlSessionTemplate() throws Exception { return new SqlSessionTemplate(studentSqlSessionFactory()); } /* * 使用这个来做总事务 后面的数据源就不用设置事务了 * */ @Bean(name = "transactionManager") @Primary public JtaTransactionManager regTransactionManager () { UserTransactionManager userTransactionManager = new UserTransactionManager(); UserTransaction userTransaction = new UserTransactionImp(); return new JtaTransactionManager(userTransaction, userTransactionManager); } } 5 Teacher配置 @ConfigurationProperties(prefix = "spring.teacher") @Data public class TeacherDataSourceProperties { /** * 数据源唯一资源名 */ private String uniqueResourceName; /** * jdbc链接URL */ private String jdbcUrl; /** * 用户名 */ private String username; /** * 密码 */ private String password; /** * 连接池 */ private Integer poolSize; /** * 数据源类名 */ private String dataSourceClassName; } @Configuration @Import(TeacherDataSourceProperties.class) @MapperScan(basePackages = "com.spring.teacher.mapper", sqlSessionFactoryRef = "teacherSqlSessionFactory") public class TeacherDatasourceConfig { @Autowired private TeacherDataSourceProperties teacherProperties; /** * 获取数据源 * ConfigurationProperties:读取spring.datasource01的数据源 */ @Bean(name = "teacherDatasource") public DataSource teacherDataSource() { //属性 Properties properties = new Properties(); properties.put("URL",teacherProperties.getJdbcUrl()); properties.put("user", teacherProperties.getUsername()); properties.put("password", teacherProperties.getPassword()); //数据源 AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean(); atomikosDataSourceBean.setUniqueResourceName(teacherProperties.getUniqueResourceName()); atomikosDataSourceBean.setXaDataSourceClassName(teacherProperties.getDataSourceClassName()); atomikosDataSourceBean.setPoolSize(teacherProperties.getPoolSize()); atomikosDataSourceBean.setXaProperties(properties); return atomikosDataSourceBean; } /** * 获取sqlSessionFactory */ @Bean public SqlSessionFactory teacherSqlSessionFactory() throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(teacherDataSource()); return factoryBean.getObject(); } /** * 获取会话模板 */ @Bean public SqlSessionTemplate teacherSqlSessionTemplate() throws Exception { return new SqlSessionTemplate(teacherSqlSessionFactory()); } } 6 po @Data @Table(name = "t_student") @AllArgsConstructor @NoArgsConstructor public class Student { @Id @Column(name = "n_id") private Integer id; @Column(name = "c_name") private String name; @Column(name = "c_age") private Integer age; } @Data @AllArgsConstructor @NoArgsConstructor @Table(name = "t_teacher") public class Teacher { @Id @Column(name = "n_id") private Integer id; @Column(name = "c_name") private String name; } 7 mapper @Mapper public interface StudentMapper extends BaseMapper { } @Mapper public interface TeacherMapper extends BaseMapper { } 8 service @Service public class CommonService { @Autowired private StudentMapper studentMapper; @Autowired private TeacherMapper teacherMapper; @Transactional public void addSuccessTest(){ studentMapper.insertSelective(new Student(null, "张三",15)); teacherMapper.insertSelective(new Teacher(null,"张三")); } @Transactional public void addRollbackTest(){ studentMapper.insertSelective(new Student(null, "张三",15)); teacherMapper.insertSelective(new Teacher(null,"张三")); int a=1/0; } } 9 启动类 @SpringBootApplication public class MybatisApplicationContext { public static void main(String[] args) { SpringApplication.run(MybatisApplicationContext.class); } } 9 测试 addSuccessTest @RunWith(SpringRunner.class) //主application方法 @SpringBootTest(classes=MybatisApplicationContext.class) public class MybatisTest { @Autowired private CommonService commonService; @Test public void addSuccessTest(){ commonService.addSuccessTest(); } @Test public void addRollbackTest(){ commonService.addRollbackTest(); } }

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

10 测试 addRollbackTest,回滚成功

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


作者:篮战丶



springboot 分布式事务 spring 分布式 分布 mybatis 事务 Mysql

需要 登录 后方可回复, 如果你还没有账号请 注册新账号