目录

1、引入依赖

2、application.yml配置文件

3、AtomikosJtaPlatform

4、事务管理器JPAAtomikosTransactionConfig

5、主数据源配置

6、其他数据源配置

7、controller层

8、service层

9、实现类

10、通用返回工具类

11、testdb包实体

12、testdb2包实体

13、testdb包持久层dao

14、testdb2包持久层dao

15、测试多数据源事务回滚


实现方式:不同的package下面的接口函数自动注入 不同的数据源

实体、dao分包存放

数据创建两个库:test库、test2库

test库中创建表如下:

CREATE TABLE `article`  (
  `id` bigint(32) NOT NULL AUTO_INCREMENT,
  `author` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `title` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `content` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `create_time` datetime(0) NULL DEFAULT NULL,
  `createTime` datetime(6) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

test2库中创建表如下:

CREATE TABLE `message`  (
  `id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'name',
  `content` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'content',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

1、引入依赖

<!--lombok-->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency><!--jpa-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency><!-- mysql-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency><!--JTA分布式事务-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>

2、application.yml配置文件

注:这里是url,不是jdbc-url

server:port: 8888
spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8datasource:primary:url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: rootpassword: '0407'driver-class-name: com.mysql.cj.jdbc.Driversecondary:url: jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: rootpassword: '0407'driver-class-name: com.mysql.cj.jdbc.Driverjpa:database-platform: org.hibernate.dialect.MySQL5InnoDBDialecthibernate:ddl-auto: validatedatabase: mysqlshow-sql: true#多数据源分布式事务jta:atomikos:datasource:max-pool-size: 20borrow-connection-timeout: 60connectionfactory:max-pool-size: 20borrow-connection-timeout: 60

3、AtomikosJtaPlatform

此类固定配置

package com.lyf.springboot.config;
import org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;public class AtomikosJtaPlatform extends AbstractJtaPlatform {private static final long serialVersionUID = 1L;static TransactionManager transactionManager;static UserTransaction transaction;@Overrideprotected TransactionManager locateTransactionManager() {return transactionManager;}@Overrideprotected UserTransaction locateUserTransaction() {return transaction;}
}

4、事务管理器JPAAtomikosTransactionConfig

固定配置

package com.lyf.springboot.config;
import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.jta.JtaTransactionManager;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;@Configuration
@ComponentScan
@EnableTransactionManagement
public class JPAAtomikosTransactionConfig {@Beanpublic PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {return new PropertySourcesPlaceholderConfigurer();}//设置JPA特性@Beanpublic JpaVendorAdapter jpaVendorAdapter() {HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();//显示sqlhibernateJpaVendorAdapter.setShowSql(true);//自动生成/更新表hibernateJpaVendorAdapter.setGenerateDdl(true);//设置数据库类型hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);return hibernateJpaVendorAdapter;}@Bean(name = "userTransaction")public UserTransaction userTransaction() throws Throwable {UserTransactionImp userTransactionImp = new UserTransactionImp();userTransactionImp.setTransactionTimeout(10000);return userTransactionImp;}@Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")public TransactionManager atomikosTransactionManager() throws Throwable {UserTransactionManager userTransactionManager = new UserTransactionManager();userTransactionManager.setForceShutdown(false);AtomikosJtaPlatform.transactionManager = userTransactionManager;return userTransactionManager;}@Bean(name = "transactionManager")@DependsOn({"userTransaction", "atomikosTransactionManager"})public PlatformTransactionManager transactionManager() throws Throwable {UserTransaction userTransaction = userTransaction();AtomikosJtaPlatform.transaction = userTransaction;TransactionManager atomikosTransactionManager = atomikosTransactionManager();return new JtaTransactionManager(userTransaction, atomikosTransactionManager);}}

5、主数据源配置

注:修改标红的部分

package com.lyf.config;import com.mysql.cj.jdbc.MysqlXADataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;@Configuration
@DependsOn("transactionManager")
@EnableJpaRepositories(basePackages = "com.lyf.dao.testdb",  //注意这里entityManagerFactoryRef = "primaryEntityManager",transactionManagerRef = "transactionManager")
public class JPAPrimaryConfig {@Resourceprivate JpaVendorAdapter jpaVendorAdapter;@Primary@Bean(name = "primaryDataSourceProperties")@ConfigurationProperties(prefix = "spring.datasource.primary")     //注意这里public DataSourceProperties primaryDataSourceProperties() {return new DataSourceProperties();}@Primary@Bean(name = "primaryDataSource", initMethod = "init", destroyMethod = "close")@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource primaryDataSource() throws SQLException {MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();mysqlXaDataSource.setUrl(primaryDataSourceProperties().getUrl());mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);mysqlXaDataSource.setPassword(primaryDataSourceProperties().getPassword());mysqlXaDataSource.setUser(primaryDataSourceProperties().getUsername());AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();xaDataSource.setXaDataSource(mysqlXaDataSource);xaDataSource.setUniqueResourceName("primary");xaDataSource.setBorrowConnectionTimeout(60);xaDataSource.setMaxPoolSize(20);return xaDataSource;}@Primary@Bean(name = "primaryEntityManager")@DependsOn("transactionManager")public LocalContainerEntityManagerFactoryBean primaryEntityManager() throws Throwable {HashMap<String, Object> properties = new HashMap<String, Object>();properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName());properties.put("javax.persistence.transactionType", "JTA");LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();entityManager.setJtaDataSource(primaryDataSource());entityManager.setJpaVendorAdapter(jpaVendorAdapter);//这里要修改成主数据源的扫描包entityManager.setPackagesToScan("com.lyf.entity.testdb");entityManager.setPersistenceUnitName("primaryPersistenceUnit");entityManager.setJpaPropertyMap(properties);return entityManager;}
}

6、其他数据源配置

package com.lyf.config;import com.mysql.cj.jdbc.MysqlXADataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;@Configuration
@DependsOn("transactionManager")
@EnableJpaRepositories(basePackages = "com.lyf.dao.testdb2",   //注意这里entityManagerFactoryRef = "secondaryEntityManager",transactionManagerRef = "transactionManager")
public class JPASecondaryConfig {@Resourceprivate JpaVendorAdapter jpaVendorAdapter;@Bean(name = "secondaryDataSourceProperties")@ConfigurationProperties(prefix = "spring.datasource.secondary")    //注意这里public DataSourceProperties masterDataSourceProperties() {return new DataSourceProperties();}@Bean(name = "secondaryDataSource", initMethod = "init", destroyMethod = "close")@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSource masterDataSource() throws SQLException {MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();mysqlXaDataSource.setUrl(masterDataSourceProperties().getUrl());mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);mysqlXaDataSource.setPassword(masterDataSourceProperties().getPassword());mysqlXaDataSource.setUser(masterDataSourceProperties().getUsername());AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();xaDataSource.setXaDataSource(mysqlXaDataSource);xaDataSource.setUniqueResourceName("secondary");xaDataSource.setBorrowConnectionTimeout(60);xaDataSource.setMaxPoolSize(20);return xaDataSource;}@Bean(name = "secondaryEntityManager")@DependsOn("transactionManager")public LocalContainerEntityManagerFactoryBean masterEntityManager() throws Throwable {HashMap<String, Object> properties = new HashMap<String, Object>();properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName());properties.put("javax.persistence.transactionType", "JTA");LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();entityManager.setJtaDataSource(masterDataSource());entityManager.setJpaVendorAdapter(jpaVendorAdapter);//这里要修改成主数据源的扫描包entityManager.setPackagesToScan("com.lyf.entity.testdb2");entityManager.setPersistenceUnitName("secondaryPersistenceUnit");entityManager.setJpaPropertyMap(properties);return entityManager;}
}

7、controller层

package com.lyf.controller;
import com.lyf.service.ArticleService;
import com.lyf.utils.AjaxResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;@Slf4j
@Controller
@RequestMapping("/rest")
public class ArticleController {@Resourceprivate ArticleService articleService;//增加一篇Article ,使用POST方法@PostMapping("/articles")public @ResponseBody AjaxResponse saveArticle(){articleService.saveArticle();return AjaxResponse.success();}}

8、service层

package com.lyf.service;
public interface ArticleService {void saveArticle();}

9、实现类

package com.lyf.service.impl;
import com.lyf.dao.testdb.ArticleRepository;
import com.lyf.dao.testdb2.MessageRepository;
import com.lyf.entity.testdb.Article;
import com.lyf.entity.testdb2.Message;
import com.lyf.service.ArticleService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;@Service
public class ArtivleServiceImpl implements ArticleService {@Resourceprivate ArticleRepository articleRepository;@Resourceprivate MessageRepository messageRepository;@Overridepublic void saveArticle() {Article article = new Article();article.setAuthor("刘耀福");article.setTitle("学习JPA多数据源分布式事务");article.setContent("学习中");article.setCreateTime(new Date());articleRepository.save(article);Message Message = new Message();Message.setName("科比");Message.setContent("打篮球");messageRepository.save(Message);}
}

10、通用返回工具类

package com.lyf.utils;
import lombok.Data;@Data
public class AjaxResponse {private boolean isok;  //请求是否处理成功private int code; //请求响应状态码(200、400、500)private String message;  //请求结果描述信息private Object data; //请求结果数据(通常用于查询操作)private AjaxResponse(){}//请求成功的响应,不带查询数据(用于删除、修改、新增接口)public static AjaxResponse success(){AjaxResponse ajaxResponse = new AjaxResponse();ajaxResponse.setIsok(true);ajaxResponse.setCode(200);ajaxResponse.setMessage("请求响应成功!");return ajaxResponse;}//请求成功的响应,带有查询数据(用于数据查询接口)public static AjaxResponse success(Object obj){AjaxResponse ajaxResponse = new AjaxResponse();ajaxResponse.setIsok(true);ajaxResponse.setCode(200);ajaxResponse.setMessage("请求响应成功!");ajaxResponse.setData(obj);return ajaxResponse;}//请求成功的响应,带有查询数据(用于数据查询接口)public static AjaxResponse success(Object obj, String message){AjaxResponse ajaxResponse = new AjaxResponse();ajaxResponse.setIsok(true);ajaxResponse.setCode(200);ajaxResponse.setMessage(message);ajaxResponse.setData(obj);return ajaxResponse;}}

11、testdb包实体

package com.lyf.entity.testdb;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.Date;@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name="article")
public class Article {@Id@GeneratedValue(strategy= GenerationType.IDENTITY)private Long id;@Column(nullable = false,length = 32)private String author;@Column(nullable = false, unique = true,length = 32)private String title;@Column(length = 512)private String content;private Date createTime;
}

12、testdb2包实体

package com.lyf.entity.testdb2;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import javax.persistence.*;@Data
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name="message")
public class Message {@Id@GeneratedValueprivate Long id;@Column(nullable = false)private String name;@Column(nullable = false)private String content;}

13、testdb包持久层dao

package com.lyf.dao.testdb;
import com.lyf.entity.testdb.Article;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ArticleRepository extends JpaRepository<Article, Long> {}

14、testdb2包持久层dao

package com.lyf.dao.testdb2;
import com.lyf.entity.testdb2.Message;
import org.springframework.data.jpa.repository.JpaRepository;
public interface MessageRepository extends JpaRepository<Message, Long> {}

15、测试多数据源事务回滚

​​​​​​​

postman测试报错,我们看看控制台

 控制台使除0异常

查看数据库事务回滚了没,回滚了

 springboot+spring data jpa 分布式事务回滚完结

SpringBoot集成Spring Data JPA多数据源(二)相关推荐

  1. hibernate mysql 读写分离_SpringBoot集成Spring Data JPA及读写分离

    JPA是什么 JPA(Java Persistence API)是Sun官方提出的Java持久化规范,它为Java开发人员提供了一种对象/关联映射工具 来管理Java应用中的关系数据.它包括以下几方面 ...

  2. spring-boot (三) spring data jpa

    学习文章来自:http://www.ityouknow.com/spring-boot.html spring data jpa介绍 首先了解JPA是什么? JPA(Java Persistence ...

  3. springboot jpa sql打印_SpringBoot集成Spring Data JPA以及读写分离

    相关代码:github OSCchina JPA是什么 JPA(Java Persistence API)是Sun官方提出的Java持久化规范,它为Java开发人员提供了一种对象/关联映射工具 来管理 ...

  4. 第九章SpringBoot整合Spring Data JPA

    目录 1 概述 2 Spring Data JPA整合 2.1 pom文件 2.2 配置文件 2.3 实体类 2.4 Dao接口 2.5 启动类 2.6 编写测试类 3 Spring Data JPA ...

  5. Spring Data JPA使用必备(二):Spring Data JPA方法命名规则实现SQL自动生成

    Spring data JPA是一个好东西,但是对于很多习惯于写SQL,直接怼数据库的人来说,这个真的用不习惯,还被一致认为是一个不易于程序员发展的技术.因为JPA提供了标准的封装,在操作数据库的时候 ...

  6. Springboot整合Spring Data JPA

    1 Spring Data JPA 1.Spring Data JPA的概念 在介绍Spring Data JPA的时候,我们首先认识下Hibernate.Hibernate是数据访问解决技术的绝对霸 ...

  7. SpringBoot的Spring Data JPA配置

    配置文件加载的优先级顺序 项目根目录下config文件夹中的配置文件 项目根目录下的配置文件 resources目录下config文件夹中的配置文件 resources目录下的配置文件 注:相应的.y ...

  8. 【Spring Data JPA自学笔记二】初识Spring Data JPA

    文章目录 Spring Data JPA是什么? Spring Data JPA的配置 配置pom.xml 配置applicationContext.xml Spring Data JPA的使用 Sp ...

  9. SpringBoot 集成 Spring Data Mongodb 操作 MongoDB 详解

    一.MongoDB 简介 MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,且与关系数据库的最为相像的.它支持的数据结构非常松散,是类似 json 的 bso ...

最新文章

  1. css去掉a标签点击后的虚线框
  2. 苹果官方 Crash文件分析方法 (iOS系统Crash文件分析方法)
  3. Android Studio 受不了了
  4. Python中的WSGI
  5. javafx 自定义控件_JavaFX自定义控件– Nest Thermostat第2部分
  6. JAVA多线程程序ProgressBar
  7. C++STL泛型编程基础知识讲解--------2015年2月3日
  8. Springboot将mybatis替换为mybatis-plus
  9. RDS SQL Server死锁(Deadlock)系列之四利用Service Broker事件通知捕获死锁
  10. 游戏云平台怎么开发_百度“云手机”与咪咕快游共建国内最大云游戏平台
  11. com线程模型实验之三
  12. 功能和界面哪个更重要
  13. Winfrom开发之动态生成TreeView树形菜单
  14. [小知识] 关于Excel中行列的固定
  15. 3dmax打开材质编辑器就崩溃
  16. Java Swing写的支持合并单元格的JTable
  17. 业务流程驱动的数字化转型,中小微企业开启转型的最简单方法论
  18. 03 HTML_网页中的表格
  19. 目前得前端框架都有哪些?
  20. Linux连接蓝牙键盘

热门文章

  1. 小米手环3复制加密门禁卡
  2. 手机app调起百度高德地图
  3. 给部分培训学生的建议
  4. 网络安全怎么学,才不会成为脚本小子?
  5. 南开大学计算机学院申请考核,南开大学2019年计算机学院“申请考核制”博士研究生招生选拔实施细则...
  6. 22-23学年计算机软件技术实习1——计算器
  7. Java基础练习题~输出100以内能同时被3和5整除的数.
  8. 中国联通物联网连接服务能力介绍
  9. QQ影音自动下载字幕乱码
  10. Greenplum集群安装配置及最佳实践