SpringBoot集成Spring Data JPA多数据源(二)
目录
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多数据源(二)相关推荐
- hibernate mysql 读写分离_SpringBoot集成Spring Data JPA及读写分离
JPA是什么 JPA(Java Persistence API)是Sun官方提出的Java持久化规范,它为Java开发人员提供了一种对象/关联映射工具 来管理Java应用中的关系数据.它包括以下几方面 ...
- spring-boot (三) spring data jpa
学习文章来自:http://www.ityouknow.com/spring-boot.html spring data jpa介绍 首先了解JPA是什么? JPA(Java Persistence ...
- springboot jpa sql打印_SpringBoot集成Spring Data JPA以及读写分离
相关代码:github OSCchina JPA是什么 JPA(Java Persistence API)是Sun官方提出的Java持久化规范,它为Java开发人员提供了一种对象/关联映射工具 来管理 ...
- 第九章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 ...
- Spring Data JPA使用必备(二):Spring Data JPA方法命名规则实现SQL自动生成
Spring data JPA是一个好东西,但是对于很多习惯于写SQL,直接怼数据库的人来说,这个真的用不习惯,还被一致认为是一个不易于程序员发展的技术.因为JPA提供了标准的封装,在操作数据库的时候 ...
- Springboot整合Spring Data JPA
1 Spring Data JPA 1.Spring Data JPA的概念 在介绍Spring Data JPA的时候,我们首先认识下Hibernate.Hibernate是数据访问解决技术的绝对霸 ...
- SpringBoot的Spring Data JPA配置
配置文件加载的优先级顺序 项目根目录下config文件夹中的配置文件 项目根目录下的配置文件 resources目录下config文件夹中的配置文件 resources目录下的配置文件 注:相应的.y ...
- 【Spring Data JPA自学笔记二】初识Spring Data JPA
文章目录 Spring Data JPA是什么? Spring Data JPA的配置 配置pom.xml 配置applicationContext.xml Spring Data JPA的使用 Sp ...
- SpringBoot 集成 Spring Data Mongodb 操作 MongoDB 详解
一.MongoDB 简介 MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,且与关系数据库的最为相像的.它支持的数据结构非常松散,是类似 json 的 bso ...
最新文章
- css去掉a标签点击后的虚线框
- 苹果官方 Crash文件分析方法 (iOS系统Crash文件分析方法)
- Android Studio 受不了了
- Python中的WSGI
- javafx 自定义控件_JavaFX自定义控件– Nest Thermostat第2部分
- JAVA多线程程序ProgressBar
- C++STL泛型编程基础知识讲解--------2015年2月3日
- Springboot将mybatis替换为mybatis-plus
- RDS SQL Server死锁(Deadlock)系列之四利用Service Broker事件通知捕获死锁
- 游戏云平台怎么开发_百度“云手机”与咪咕快游共建国内最大云游戏平台
- com线程模型实验之三
- 功能和界面哪个更重要
- Winfrom开发之动态生成TreeView树形菜单
- [小知识] 关于Excel中行列的固定
- 3dmax打开材质编辑器就崩溃
- Java Swing写的支持合并单元格的JTable
- 业务流程驱动的数字化转型,中小微企业开启转型的最简单方法论
- 03 HTML_网页中的表格
- 目前得前端框架都有哪些?
- Linux连接蓝牙键盘