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

news/2024/7/4 9:33:19

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) 工程
在这里插入图片描述

2 pom

<!--spring boot 版本依赖-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <!-- spring boot 对 web的依赖 可用 spring-boot:run启动 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- spring boot 测试 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 测试包 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>
        <!--mapper -->
        <!-- https://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>
        <!--pagehelper -->
        <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.10</version>
        </dependency>
        <!-- MySQL 连接驱动依赖 -->
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jta-atomikos</artifactId>
        </dependency>
    </dependencies>

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<Student> {
}

@Mapper
public interface TeacherMapper extends BaseMapper<Teacher> {
}

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,回滚成功

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


http://www.niftyadmin.cn/n/4556839.html

相关文章

我学的是园林设计 大学里的4级补习班和电脑C语言班 那个更有用些

如果你想在计算机方面发展 没什么用处 ||| 其实如果你不是计算机专业而且不希望将来从事计算机专业工作的话 那个东西学一点点 我的意见是放弃C语言的学习 所以把C语言的语法自己看会了就行了 网上搜索:C语言教程 或电子书.就OK拉 ||| 如果你不是学计算机专业的 大学4级靠的一般…

数据检验插件: Validate插件 添加自定义表单验证

jQuery.validator.addMethod("ValiPass", function(value, element,params) { var exp new RegExp(params);//实例化正则对象&#xff0c;参数为传入的正则表达式 return exp.test(value); //测试是否匹配 }, "密码必须包含数字、字母大、小写、符号四种&…

员工考勤管理系统

search%E8%80%83%E5%8B%A4%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F&restype-1&id10000001&ty0&pattern0 还有专门的论坛Google里面找一找 答案补充 http://code.knowsky.com/down/5050.html这个网站C的有 我不专业 东西已经发到邮箱了 我不参加评分 两天没上QQ了…

Flink on yarn的问题:Invalid AMRMToken

目前采用的Flink的版本是1.4.2&#xff0c;运行在yarn上&#xff0c;总是时不时的报错“Invalid AMRMToken from appattempt”&#xff0c;导致AM挂掉。 简而言之&#xff0c;就是AM和RM沟通的过程中&#xff0c;突然AM提供的Token不被认可&#xff0c;导致拒绝连接&#xff0c…

【Spring源码解析】BeanFactoryPostProcessor【相关类】源码解析

1 BeanFactoryPostProcessor作用 public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {/*** 可以修改容器Bean内部的定义信息&#xff0c;全部的bean definitions会加载但是bean没有被实例化*/void postProcessBeanDefinitionRegistry(B…

怎样才可以编程序

||| 编程序需要编程软件的 再把MFC学好的话 我只能这样告诉你了 ||| 你已经学了C 以上建议 碰到问题查帮助;久而久之 里面还包含实用的例子;边学边做项目 很容易就可以找到你想要的答案 你就可以查看里面帮助文件;使用索引和查找功能 你可以到CSDN 上面收集另外 VF C语言 模拟电…

Django 模型层之多表操作

一.创建模型 实例: 作者表:拥有字段:姓名(name),性别(sex),该表与书籍表之间为多对多的关系 作者详情表:拥有字段:地址(addr),手机号(phone),该表与作者表之间为一对一的关系 出版社表:拥有字段:名字(name),地址(addr),该表与书籍表之间为一对多的关系 书籍表:拥有字段:书名(na…

【Spring源码解析】 IOC 初始化流程分析

1 .AbstractApplicationContext prepareBeanFactory Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//刷新前预处理prepareRefresh();//获取beanFactory实例。(DefaultListableBeanFactory)Conf…