springBoot⼊门总结(⼋)使⽤jta+atomikos整合springBoot分
布式事务resource和autowired注解的区别
⼀、JTA:Java Transaction Manager
事务是计算机应⽤中不可或缺的组件模型,它保证了⽤户操作的原⼦性 ( Atomicity )、⼀致性 ( Consistency )、隔离性 ( Isolation ) 和持久性 ( Durabilily )。
JTA:(Java Transaction Manager)是Java 中对事务进⾏管理的接⼝,在Java应⽤中,调⽤者实际上便是通过调⽤事务接⼝来实现事务的管理。
如果⼀个应⽤中存在多个不同的数据源,通常我们会创建多个数据源的事务管理器。
⽐如⼀个Java应⽤需要调⽤两个不同的数据源,那么我们就需要创建两个DataSourceTransactionManager分别来对数据库事务进⾏管理。
假如在⼀次服务的请求过程中,需要同时调⽤两个数据源,我们都知道必须要保证事务的⼀致性 ( Consistency )。
public void service {
//业务A
transaction A
//业务B
transaction B
}
假设, transaction A 提交成功后,继续执⾏业务B抛出了异常,但是由于transaction A已经提交了,数据库已经插⼊不能进⾏回滚操作,那么这将导致⽆法满⾜事务的⼀致性。
JTA就是⽤来解决在同时访问多个数据源时,可能出现的数据不⼀致问题。
JTA的特点
1. 两阶段提交
2. 事务时间太长,锁数据太长
3. 低性能,低吞吐量
JTA是如何实现多数据源的事务管理呢?
主要的原理是两阶段提交,以上⾯的请求为例,当整个业务完成了之后只是第⼀阶段提交,在第⼆阶段提交之前,会检查其他所有事务是否已经提交,如果发现整个请求过程中出现了错误或是没有提交等情况,那么第⼆阶段就不会提交,⽽是直接rollback操作,这样所有的事务都会做Rollback操作。
⼆、atomikos:Atomikos TransactionsEssentials
Atomikos是JTA的实现,spring boot中引⼊依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
三、多数据源的事务管理
1、本地数据库 test01、test02
库中分别新建表 t_user 字段 id(主键id⾃增)、name(姓名)、age(年龄)2、创建项⽬,并将 jta-atomikos 引⼊pom⽂件。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId&batis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
</dependency>
<dependency>
<groupId&batis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
3、application.properties配置多数据源
# Mysql 1
st1.sql.cj.jdbc.Driver
st1.jdbc-url=jdbc:mysql://localhost:3306/test01?useUnicode=true&characterEnc
oding=utf-8&serverTimezone=UTC st1.username=root
st1.password=1q2w3e4r5t
st1.minPoolSize = 3
st1.maxPoolSize = 25
st1.maxLifetime = 20000
st1.borrowConnectionTimeout = 30
st1.loginTimeout = 30
st1.maintenanceInterval = 60
st1.maxIdleTime = 60
# Mysql 2
st2.sql.cj.jdbc.Driver
st2.jdbc-url=jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC st2.username=root
st2.password=1q2w3e4r5t
st2.minPoolSize = 3
st2.maxPoolSize = 25
st2.maxLifetime = 20000
st2.borrowConnectionTimeout = 30
st2.loginTimeout = 30
st2.maintenanceInterval = 60
st2.maxIdleTime = 60
4、新建数据源实体类 DBConfig1、DBConfig2
@Data //lombok
@ConfigurationProperties(prefix = "st1") //读取配置⽂件中以 st1 开始的配置
public class DBConfig1 {
private String url;
private String username;
private String password;
private int minPoolSize;
private int maxPoolSize;
private int maxLifetime;
private int borrowConnectionTimeout;
private int loginTimeout;
private int maintenanceInterval;
private int maxIdleTime;
private String testQuery;
}
@Data //lombok
@ConfigurationProperties(prefix = "st2") //读取配置⽂件中以 st2 开始的配置
public class DBConfig1 {
private String url;
private String username;
private String password;
private int minPoolSize;
private int maxPoolSize;
private int maxLifetime;
private int borrowConnectionTimeout;
private int loginTimeout;
private int maintenanceInterval;
private int maxIdleTime;
private String testQuery;
}
注意:新建数据源实体类,需要在启动⽂件中使⽤ @EnableConfigurationProperties 注解加载配置类 @EnableConfigurationProperties(value = {DBConfig1.class, DBConfig2.class})
5、创建业务⽤户实体类对象(lombok)
@Data
public class User {
private Integer id;
private String name;
private Integer age;
}
6、mapper接⼝
package com.demo.datasource.mapper1;
import ity.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserMapper1 {
@Insert("insert into t_user(name,age) values (#{name},#{age})")
void save(User user);
}
package com.demo.datasource.mapper2;
import ity.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserMapper2 {
@Insert("insert into t_user(name,age) values (#{name},#{age})")
void save(User user);
}
7、新建数据源配置⽂件 DataSourceConfig01、DataSourceConfig02
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论