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;
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;
@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;
}
@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;
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;
@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;
}
@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)
@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,回滚成功