Spring Boot2 系列教程(二十五)Spring Boot 整合 Jpa 多数据源
本文是 Spring Boot 整合数据持久化方案的最后一篇,主要和大伙来聊聊 Spring Boot 整合 Jpa 多数据源问题。在 Spring Boot 整合JbdcTemplate 多数据源、Spring Boot 整合 MyBatis 多数据源以及 Spring Boot 整合 Jpa 多数据源这三个知识点中,整合 Jpa 多数据源算是最复杂的一种,也是很多人在配置时最容易出错的一种。本文大伙就跟着松哥的教程,一步一步整合 Jpa 多数据源。
工程创建
首先是创建一个 Spring Boot 工程,创建时添加基本的 Web、Jpa 以及 MySQL 依赖,如下:

创建完成后,添加 Druid 依赖,这里和前文的要求一样,要使用专为 Spring Boot 打造的 Druid,大伙可能发现了,如果整合多数据源一定要使用这个依赖,因为这个依赖中才有 DruidDataSourceBuilder,最后还要记得锁定数据库依赖的版本,因为可能大部分人用的还是 5.x 的 MySQL 而不是 8.x。完整依赖如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.28</version>
<scope>runtime</scope>
</dependency>
如此之后,工程就创建成功了。
基本配置
在基本配置中,我们首先来配置多数据源基本信息以及 DataSource,首先在 application.properties 中添加如下配置信息:
# 数据源一
spring.datasource.one.username=root
spring.datasource.one.password=root
spring.datasource.one.url=jdbc:mysql:///test01?useUnicode=true&characterEncoding=UTF-8
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource
# 数据源二
spring.datasource.two.username=root
spring.datasource.two.password=root
spring.datasource.two.url=jdbc:mysql:///test02?useUnicode=true&characterEncoding=UTF-8
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource
# Jpa配置
spring.jpa.properties.database=mysql
spring.jpa.properties.show-sql=true
spring.jpa.properties.database-platform=mysql
spring.jpa.properties.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
这里 Jpa 的配置和上文相比 key 中多了 properties,多数据源的配置和前文一致,然后接下来配置两个 DataSource,如下:
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.one")
@Primary
DataSource dsOne() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.two")
DataSource dsTwo() {
return DruidDataSourceBuilder.create().build();
}
}
这里的配置和前文的多数据源配置基本一致,但是注意多了一个在 Spring 中使用较少的注解 @Primary,这个注解一定不能少,否则在项目启动时会出错,@Primary 表示当某一个类存在多个实例时,优先使用哪个实例。
好了,这样,DataSource 就有了。
多数据源配置
接下来配置 Jpa 的基本信息,这里两个数据源,我分别在两个类中来配置,先来看第一个配置:
@Configuration
@EnableJpaRepositories(basePackages = "org.javaboy.jpa.dao",entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanOne",transactionManagerRef = "platformTransactionManagerOne")
public class JpaConfigOne {
@Autowired
@Qualifier(value = "dsOne")
DataSource dsOne;
@Autowired
JpaProperties jpaProperties;
@Bean
@Primary
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanOne(EntityManagerFactoryBuilder builder) {
return builder.dataSource(dsOne)
.packages("org.javaboy.jpa.model")
.properties(jpaProperties.getProperties())
.persistenceUnit("pu1")
.build();
}
@Bean
PlatformTransactionManager platformTransactionManagerOne(EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean factoryBeanOne = localContainerEntityManagerFactoryBeanOne(builder);
return new JpaTransactionManager(factoryBeanOne.getObject());
}
}
首先这里注入 dsOne,再注入 JpaProperties,JpaProperties 是系统提供的一个实例,里边的数据就是我们在 application.properties 中配置的 jpa 相关的配置。然后我们提供两个 Bean,分别是 LocalContainerEntityManagerFactoryBean 和 PlatformTransactionManager 事务管理器,不同于 MyBatis 和 JdbcTemplate,在 Jpa 中,事务一定要配置。在提供 LocalContainerEntityManagerFactoryBean 的时候,需要指定 packages,这里的 packages 指定的包就是这个数据源对应的实体类所在的位置,另外在这里配置类上通过 @EnableJpaRepositories 注解指定 dao 所在的位置,以及 LocalContainerEntityManagerFactoryBean 和 PlatformTransactionManager 分别对应的引用的名字。
好了,这样第一个就配置好了,第二个基本和这个类似,主要有几个不同点:
- dao 的位置不同
- persistenceUnit 不同
- 相关 bean 的名称不同
注意实体类可以共用。
代码如下:
@Configuration
@EnableJpaRepositories(basePackages = "org.javaboy.jpa.dao2",entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanTwo",transactionManagerRef = "platformTransactionManagerTwo")
public class JpaConfigTwo {
@Autowired
@Qualifier(value = "dsTwo")
DataSource dsTwo;
@Autowired
JpaProperties jpaProperties;
@Bean
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanTwo(EntityManagerFactoryBuilder builder) {
return builder.dataSource(dsTwo)
.packages("org.javaboy.jpa.model")
.properties(jpaProperties.getProperties())
.persistenceUnit("pu2")
.build();
}
@Bean
PlatformTransactionManager platformTransactionManagerTwo(EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean factoryBeanTwo = localContainerEntityManagerFactoryBeanTwo(builder);
return new JpaTransactionManager(factoryBeanTwo.getObject());
}
}
接下来,在对应位置分别提供相关的实体类和 dao 即可,数据源一的 dao 如下:
package org.javaboy.jpa.dao;
public interface UserDao extends JpaRepository<User,Integer> {
List<User> getUserByAddressEqualsAndIdLessThanEqual(String address, Integer id);
@Query(value = "select * from t_user where id=(select max(id) from t_user)",nativeQuery = true)
User maxIdUser();
}
数据源二的 dao 如下:
package org.javaboy.jpa.dao2;
public interface UserDao2 extends JpaRepository<User,Integer> {
List<User> getUserByAddressEqualsAndIdLessThanEqual(String address, Integer id);
@Query(value = "select * from t_user where id=(select max(id) from t_user)",nativeQuery = true)
User maxIdUser();
}
共同的实体类如下:
package org.javaboy.jpa.model;
@Entity(name = "t_user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String username;
private String address;
//省略getter/setter
}
到此,所有的配置就算完成了,接下来就可以在 Service 中注入不同的 UserDao,不同的 UserDao 操作不同的数据源。
其实整合 Jpa 多数据源也不算难,就是有几个细节问题,这些细节问题解决,其实前面介绍的其他多数据源整个都差不多。
好了,本文就先介绍到这里。
相关案例已经上传到 GitHub,欢迎小伙伴们们下载:https://github.com/lenve/javaboy-code-samples
扫码关注松哥,公众号后台回复 2TB,获取松哥独家 超2TB 免费 Java 学习干货

Spring Boot2 系列教程(二十五)Spring Boot 整合 Jpa 多数据源的更多相关文章
- Spring Boot2 系列教程(二十六)Spring Boot 整合 Redis
在 Redis 出现之前,我们的缓存框架各种各样,有了 Redis ,缓存方案基本上都统一了,关于 Redis,松哥之前有一个系列教程,尚不了解 Redis 的小伙伴可以参考这个教程: Redis 教 ...
- Spring Boot2 系列教程(二十八)Spring Boot 整合 Session 共享
这篇文章是松哥的原创,但是在第一次发布的时候,忘了标记原创,结果被好多号转发,导致我后来整理的时候自己没法标记原创了.写了几百篇原创技术干货了,有一两篇忘记标记原创进而造成的一点点小小损失也能接受,不 ...
- Spring Boot2 系列教程(二十四)Spring Boot 整合 Jpa
Spring Boot 中的数据持久化方案前面给大伙介绍了两种了,一个是 JdbcTemplate,还有一个 MyBatis,JdbcTemplate 配置简单,使用也简单,但是功能也非常有限,MyB ...
- Spring Boot2 系列教程(二十九)Spring Boot 整合 Redis
经过 Spring Boot 的整合封装与自动化配置,在 Spring Boot 中整合Redis 已经变得非常容易了,开发者只需要引入 Spring Data Redis 依赖,然后简单配下 red ...
- Spring Boot2 系列教程(二十)Spring Boot 整合JdbcTemplate 多数据源
多数据源配置也算是一个常见的开发需求,Spring 和 SpringBoot 中,对此都有相应的解决方案,不过一般来说,如果有多数据源的需求,我还是建议首选分布式数据库中间件 MyCat 去解决相关问 ...
- Spring Boot2 系列教程(二十三)理解 Spring Data Jpa
有很多读者留言希望松哥能好好聊聊 Spring Data Jpa! 其实这个话题松哥以前零零散散的介绍过,在我的书里也有介绍过,但是在公众号中还没和大伙聊过,因此本文就和大家来仔细聊聊 Spring ...
- Spring Boot2 系列教程(二十二)整合 MyBatis 多数据源
关于多数据源的配置,前面和大伙介绍过 JdbcTemplate 多数据源配置,那个比较简单,本文来和大伙说说 MyBatis 多数据源的配置. 其实关于多数据源,我的态度还是和之前一样,复杂的就直接上 ...
- Spring Boot2 系列教程(三十)Spring Boot 整合 Ehcache
用惯了 Redis ,很多人已经忘记了还有另一个缓存方案 Ehcache ,是的,在 Redis 一统江湖的时代,Ehcache 渐渐有点没落了,不过,我们还是有必要了解下 Ehcache ,在有的场 ...
- Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇
Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇 本文主要内容: 1:spring cloud整合Eureka总结 本文是由凯哥(凯哥Java:kagejava ...
随机推荐
- Kubernetes的Ingress简单入门
目录 一.什么是Ingress 二.部署Nginx Ingress Controller 三.部署一个Service将Nginx服务暴露出去 四.部署一个我们自己的服务Cafe 五.部署ingress ...
- 我要学并发-Java内存模型到底是什么
内存模型 在计算机CPU,内存,IO三者之间速度差异,为了提高系统性能,对这三者速度进行平衡. CPU 增加了缓存,以均衡与内存的速度差异: 操作系统增加了进程.线程,以分时复用 CPU,进而均衡 C ...
- Java Web项目中使用Freemarker生成Word文档遇到的问题
这段时间项目中使用了freemarker生成word文档.在项目中遇到了几个问题,在这里记录一下.首先就是关于遍历遇到的坑.整行整行的遍历是很简单的,只需要在整行的<w:tr></w ...
- vue系列---响应式原理实现及Observer源码解析(一)
_ 阅读目录 一. 什么是响应式? 二:如何侦测数据的变化? 2.1 Object.defineProperty() 侦测对象属性值变化 2.2 如何侦测数组的索引值的变化 2.3 如何监听数组内容的 ...
- 百万年薪python之路 -- 推导式
2.1列表推导式 首先我们先看一下这样的代码,给出一个列表,通过循环,想列表中添加1~10: li = [] for i in range(1,11): li.append(i) print(li) ...
- 轻量级CNN模型mobilenet v1
mobilenet v1 论文解读 论文地址:https://arxiv.org/abs/1704.04861 核心思想就是通过depthwise conv替代普通conv. 有关depthwise ...
- 解压zip文件
/// <summary> /// 执行压缩命令结果 /// </summary> public enum CompressResults { Success, SourceO ...
- Unity Dropdown
unity DropDown控件应用很简单 代码如下 frameDpdown.options.Clear(); //Dropdown.OptionData optDataFrame = new Dro ...
- stream流篇
流是C#中比较重要的一个概念,很多关键技术都需要用到流.何为流呢?可以理解流为江河中水的流动,不过C#中则为信息流,我们可以把信息写入流,也可以读出.比如以文件读写操作为例,首先以某种方式(如只读)打 ...
- 利用span设置文字固定宽度
<input type="radio" name="dispMode" id="rdoManul" value="manul ...