实体类
package com.example.jta.entity.db1;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Goods {
private Long id;
private String name;
}
package com.example.jta.entity.db2;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
import java.util.Date;
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private Long id;
private String username;
private Date birthday;
private String sex;
private String address;
}
结构图
3.依赖
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.2.6.RELEASE
com.example
jta-mybatis
0.0.1-SNAPSHOT
jta-mybatis
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
8.0.11
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.2.0
org.springframework.boot
spring-boot-starter-jta-atomikos
com.alibaba
druid
1.1.21
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
src/main/java
**
@Configuration
@MapperScan(basePackages = "com.example.jta.dao.db1",sqlSessionFactoryRef = "goodsSqlSessionFactory",sqlSessionTemplateRef = "goodsSqlSessionTemplate")
public class GoodsDataSourceConfig {
@Value("${spring.datasource.db1.jdbc-url}")
private String jdbcUrl;
@Value("${spring.datasource.db1.username}")
private String username;
@Value("${spring.datasource.db1.password}")
private String password;
@Primary
@Bean(name = "goodsDataSource")
public DataSource goodsDataSource() {
DruidXADataSource druidXADataSource = new DruidXADataSource();
druidXADataSource.setUrl(jdbcUrl);
druidXADataSource.setUsername(username);
druidXADataSource.setPassword(password);
druidXADataSource.setDefaultAutoCommit(false);
AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
atomikosDataSourceBean.setXaDataSource(druidXADataSource);
atomikosDataSourceBean.setUniqueResourceName("goodsDataSource");
atomikosDataSourceBean.setPoolSize(5);
return atomikosDataSourceBean;
}
@Bean(name = "goodsSqlSessionFactory")
SqlSessionFactory goodsSqlSessionFactory(@Qualifier(value = "goodsDataSource")DataSource goodsDataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(goodsDataSource);
return factoryBean.getObject();
}
@Bean(name = "goodsSqlSessionTemplate")
SqlSessionTemplate goodsSqlSessionTemplate(@Qualifier(value = "goodsSqlSessionFactory")SqlSessionFactory goodsSqlSessionFactory) {
return new SqlSessionTemplate(goodsSqlSessionFactory);
}
}
package com.example.jta.config;
import com.alibaba.druid.pool.xa.DruidXADataSource;
import com.atomikos.jdbc.AtomikosDataSourceBean;
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.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.example.jta.dao.db2",sqlSessionFactoryRef = "userSqlSessionFactory",sqlSessionTemplateRef = "userSqlSessionTemplate")
public class UserDataSourceConfig {
@Value("${spring.datasource.db2.jdbc-url}")
private String jdbcUrl;
@Value("${spring.datasource.db2.username}")
private String username;
@Value("${spring.datasource.db2.password}")
private String password;
@Bean(name = "userDataSource")
public DataSource userDataSource() {
DruidXADataSource druidXADataSource = new DruidXADataSource();
druidXADataSource.setUrl(jdbcUrl);
druidXADataSource.setUsername(username);
druidXADataSource.setPassword(password);
druidXADataSource.setDefaultAutoCommit(false);
AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
atomikosDataSourceBean.setXaDataSource(druidXADataSource);
atomikosDataSourceBean.setUniqueResourceName("userDataSource");
atomikosDataSourceBean.setPoolSize(5);
return atomikosDataSourceBean;
}
@Bean(name = "userSqlSessionFactory")
SqlSessionFactory userSqlSessionFactory(@Qualifier(value = "userDataSource")DataSource userDataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(userDataSource);
return factoryBean.getObject();
}
@Bean(name = "userSqlSessionTemplate")
SqlSessionTemplate userSqlSessionTemplate(@Qualifier(value = "userSqlSessionFactory")SqlSessionFactory userSqlSessionFactory) {
return new SqlSessionTemplate(userSqlSessionFactory);
}
}
package com.example.jta.config;
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.Primary;
import org.springframework.transaction.jta.JtaTransactionManager;
import javax.transaction.UserTransaction;
@Configuration
public class JtaTransactionManagerConfig {
@Primary
@Bean(name = "jtaTransactionManager")
public JtaTransactionManager regTransactionManager () {
UserTransactionManager userTransactionManager = new UserTransactionManager();
UserTransaction userTransaction = new UserTransactionImp();
return new JtaTransactionManager(userTransaction, userTransactionManager);
}
}
6.控制层Controller
package com.example.jta.controller;
import com.example.jta.entity.db1.Goods;
import com.example.jta.entity.db2.User;
import com.example.jta.service.GoodsService;
import com.example.jta.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
@RestController
public class TransactionController {
@Autowired
private UserService userService;
@Autowired
private GoodsService goodsService;
@Transactional(value = "jtaTransactionManager", rollbackFor = Exception.class)
@GetMapping("/add")
public ResponseEntity addTest() {
Goods goods = new Goods();
goods.setId(1L);
goods.setName("涡轮发动机");
goodsService.addGoods(goods);
User user = new User();
user.setSex("男");
user.setUsername("周杰伦");
user.setAddress("上海");
user.setBirthday(new Date());
userService.addUser(user);
return ResponseEntity.ok("添加成功");
}
//在该接口中故意制造一个除零异常
@Transactional(value = "jtaTransactionManager", rollbackFor = Exception.class)
@GetMapping("/add2")
public ResponseEntity addTest2() {
Goods goods = new Goods();
goods.setId(2L);
goods.setName("兰博基尼");
goodsService.addGoods(goods);
User user = new User();
user.setSex("男");
user.setUsername("周润发");
user.setAddress("上海");
user.setBirthday(new Date());
userService.addUser(user);
int i = 10 / 0;
return ResponseEntity.ok("添加成功");
}
}
7.业务层Service
package com.example.jta.service;
import com.example.jta.entity.db1.Goods;
public interface GoodsService {
void addGoods(Goods goods);
}
package com.example.jta.service;
import com.example.jta.entity.db2.User;
public interface UserService {
void addUser(User user);
}
package com.example.jta.service.impl;
import com.example.jta.dao.db1.GoodsMapper;
import com.example.jta.entity.db1.Goods;
import com.example.jta.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
@Service
public class GoodsServiceImpl implements GoodsService {
@Autowired
private GoodsMapper goodsMapper;
@Override
public void addGoods(Goods goods) {
try {
goodsMapper.addGoods(goods);
}catch (Exception e){
//强制手动事务回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackonly();
}
}
}
package com.example.jta.service.impl;
import com.example.jta.dao.db2.UserMapper;
import com.example.jta.entity.db2.User;
import com.example.jta.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public void addUser(User user) {
try {
userMapper.addUser(user);
} catch (Exception e) {
//强制手动事务回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackonly();
}
}
}
8.持久层Dao
package com.example.jta.dao.db1;
import com.example.jta.entity.db1.Goods;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface GoodsMapper {
void addGoods(Goods goods);
}
package com.example.jta.dao.db2;
import com.example.jta.entity.db2.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper {
void addUser(User user);
}
INSERT INTO goods(id, name) VALUES (#{id}, #{name});
INSERT INTO user(id, address, birthday, sex, username) VALUES (#{id}, #{address}, #{birthday}, #{sex}, #{username});
9.启动类
package com.example.jta;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
//手动进行事务管理
@EnableTransactionManagement
public class JtaMybatisApplication {
public static void main(String[] args) {
SpringApplication.run(JtaMybatisApplication.class, args);
}
}