二八佳人体似酥,腰间仗剑斩愚夫。虽然不见人头落,暗里教君骨髓枯。

上一章简单介绍了多数据源配置JdbcTemplate(十五),如果没有看过,​​请观看上一章​​

工作中,在业务的发展或业务数据隔离的场景下,通常需要一个项目中引入多个数据源,

但SpringBoot默认的自动化配置是单数据源的,可以通过一些额外的配置,进行处理。

一. 多数据源配置前的工作准备

一.一 准备两个数据库 springboot 和springboot2

springboot 数据库里面存放着 user 表

springboot2 数据库表里面存放着 dept 表

-- 在 springboot 数据库里面 创建 user 表
use springboot;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(15) DEFAULT NULL,
`sex` varchar(20) DEFAULT NULL,
`age` int(6) DEFAULT NULL,
`description` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- 在 springboot2 数据库里面 创建 dept 表
use springboot2;
CREATE TABLE `dept` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

一.二 准备对应的实体 User.java 和 Dept.java

User.java

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
/**
* @param id id编号
* @param name 姓名
* @param sex 性别
* @param age 年龄
* @param description 描述
*/
private Integer id;
private String name;
private String sex;
private Integer age;
private String description;
}

Dept.java

@Data
public class Dept {
/**
* @param id id编号
* @param name 部门名称
*/
private Integer id;
private String name;
}

一.三 Jpa 的使用

关于 Jpa 的使用,可以看老蝴蝶以前写的文章: ​​SpringBoot整合JPA(六)​​

项目目录:

多数据源配置Jpa(十六)_java

二. Jpa 多数据源配置

二.一 pom.xml 添加依赖

<!--引入MySql的驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--引入springboot与jpa整合的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>

二.二 application.yml 配置多数据源

# 配置成多数据源的形式
spring:
datasource:
# 以前的配置,去掉
#driver-class-name: com.mysql.cj.jdbc.Driver
#url: jdbc:mysql://localhost:3306/springboot?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false
#username: root
#password: abc123
# 配置第一个数据库
one:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: root
password: abc123
type: com.alibaba.druid.pool.DruidDataSource
# 配置第二个数据库
two:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot2?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: root
password: abc123
type: com.alibaba.druid.pool.DruidDataSource
# JPA的相关配置
jpa:
# 设置数据库平台
database-platform: org.hibernate.dialect.MySQLDialect
# 设置数据库
database: mysql
# 是否展示SQL语句
show-sql: true
hibernate:
use-new-id-generator-mappings: false
# 持久化规则是 update
ddl-auto: update
naming:
# 物理命名策略类的全限定名称
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

二.三 实体配置

在 pojo 包下, 分别创建两个包 one 和 two 包。

one 包下面放置所有使用 one 数据库实体的信息, two 包下面放置所有使用two数据库实体的信息

多数据源配置Jpa(十六)_java_02

二.三.一 User.java 用户实体

@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "user")
@Entity
public class User implements Serializable {
/**
* @param id id编号
* @param name 姓名
* @param sex 性别
* @param age 年龄
* @param description 描述
*/
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Integer id;
@Column(name = "name")
private String name;
@Column(name="sex")
private String sex;
@Column(name="age")
private Integer age;
@Column(name="description")
private String description;
}

二.三.二 Dept.java 部门实体

@Data
@Table(name = "dept")
@Entity
public class Dept {
/**
* @param id id编号
* @param name 部门名称
*/
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Integer id;
@Column(name = "name")
private String name;
}

二.四 repository 仓库配置

在 repository 包下, 创建 one 包和 two包

one 包下面放置所有使用 one 数据库的信息, two 包下面放置所有使用two数据库的信息

多数据源配置Jpa(十六)_java_03

二.四.一 UserRepository 接口

public interface UserRepository extends JpaRepository<User, Integer>,
JpaSpecificationExecutor<User>{
// 其他的方法. 具体使用可以参考 Jpa章节
}

二.四.二 DeptRepository 接口

public interface DeptRepository extends JpaRepository<Dept, Integer>,
JpaSpecificationExecutor<Dept>{
// 其他的方法. 具体使用可以参考 Jpa章节
}

二.五 数据多数据源配置

主要配置 数据源 DataSource 和关于扫描库,扫描实体。

多数据源配置Jpa(十六)_java_04

二.五.一 DataSource 数据源配置

package top.yueshushu.learn.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;

/**
* @ClassName:DataSourceConfig
* @Description 数据库源的配置
* @Author zk_yjl
* @Date 2021/9/2 10:42
* @Version 1.0
* @Since 1.0
**/
@Component
public class DataSourceConfig {
/**
* 创建 springboot 的数据库的数据源 DataSource
* @return
*/
@Bean("dataSourceOne")
@ConfigurationProperties("spring.datasource.one")
@Primary //通过注解 @Primary 表明默认的库
public DataSource dataSourceOne(){

return DruidDataSourceBuilder.create().build();
}
/**
* 创建 springboot2 的数据库的数据源 DataSource
* @return
*/
@Bean("dataSourceTwo")
@ConfigurationProperties("spring.datasource.two")
public DataSource dataSourceTwo(){

return DruidDataSourceBuilder.create().build();
}
}

在 dataSourceOne() 方法上,多添加了一个注解 @Primary ,指定默认的库。 默认库为 springboot

二.五.二 配置扫描库和扫描实体

二.五.二.一 配置主库 dataSourceOne 数据源

package top.yueshushu.learn.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.sql.DataSource;

/**
* @ClassName:JpaOneConfig
* @Description 数据库 springboot的Jpa 主库 配置信息
* @Author zk_yjl
* @Date 2021/9/6 18:00
* @Version 1.0
* @Since 1.0
**/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "top.yueshushu.learn.repository.one", // 指定扫描仓库的位置
entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanOne", //指定扫描实体的位置
transactionManagerRef = "platformTransactionManagerOne") //指定事务
public class JpaOneConfig {
@Resource(name="dataSourceOne")
DataSource dataSourceOne;
@Autowired
JpaProperties jpaProperties;

@Primary //配置默认
@Bean(name = "entityManagerPrimaryOne")
public EntityManager entityManagerOne(EntityManagerFactoryBuilder builder) {
return localContainerEntityManagerFactoryBeanOne(builder).getObject().createEntityManager();
}

@Bean
@Primary //配置默认
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanOne(EntityManagerFactoryBuilder builder) {
return builder.dataSource(dataSourceOne)
// 设置实体的包
.packages("top.yueshushu.learn.pojo.one")
//设置配置信息
.properties(jpaProperties.getProperties())
//设置持久化的名称
.persistenceUnit("onePersistenceUnit")
.build();
}
@Bean
@Primary //配置默认
PlatformTransactionManager platformTransactionManagerOne(EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean factoryBeanOne = localContainerEntityManagerFactoryBeanOne(builder);
return new JpaTransactionManager(factoryBeanOne.getObject());
}
}

二.五.二.二 配置从库 dataSourceOne 数据源

package top.yueshushu.learn.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.sql.DataSource;

/**
* @ClassName:JpaOneConfig
* @Description 数据库 springboot的Jpa配置信息
* @Author zk_yjl
* @Date 2021/9/6 18:00
* @Version 1.0
* @Since 1.0
**/
@Configuration
@EnableJpaRepositories(basePackages = "top.yueshushu.learn.repository.two", // 指定扫描仓库的位置
entityManagerFactoryRef ="localContainerEntityManagerFactoryBeanTwo", //指定扫描实体的位置
transactionManagerRef = "platformTransactionManagerTwo") //指定事务
@EnableTransactionManagement
public class JpaTwoConfig {

@Resource(name="dataSourceTwo")
DataSource dataSourceTwo;
@Autowired
JpaProperties jpaProperties;


@Bean(name = "entityManagerTwo")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return localContainerEntityManagerFactoryBeanTwo(builder).getObject().createEntityManager();
}

@Bean
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanTwo(EntityManagerFactoryBuilder builder) {
return builder.dataSource(dataSourceTwo)
.packages("top.yueshushu.learn.pojo.two")
.properties(jpaProperties.getProperties())
//设置持久化的名称
.persistenceUnit("twoPersistenceUnit")
.build();
}
@Bean
PlatformTransactionManager platformTransactionManagerTwo(EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean factoryBeanTwo = localContainerEntityManagerFactoryBeanTwo(builder);
return new JpaTransactionManager(factoryBeanTwo.getObject());
}
}

二.六 接口及其实现

UserService.java 接口

public interface UserService {

void addUser(User user);

List<User> listUser();

void addDept(Dept dept);

List<Dept> listDept();
}

UserServiceImpl.java 实现类

@Service
public class UserServiceImpl implements UserService {
// 数据源1 放置到 springboot 数据库里面
@Resource
private UserRepository userRepository;
//数据源2, 放置到 springboot2 数据库里面
@Resource
private DeptRepository deptRepository;

/**
* 使用的是数据源 springboot
*/
@Override
public void addUser(User user) {
userRepository.save(user);
}
/**
* 使用的是数据源 springboot
*/
@Override
public List<User> listUser() {
return userRepository.findAll();
}
/**
* 使用的是数据源 springboot2
*/
@Override
public void addDept(Dept dept) {
deptRepository.save(dept);
}
/**
* 使用的是数据源 springboot2
*/
@Override
public List<Dept> listDept() {
return deptRepository.findAll();
}
}

二.七 测试

二.七.一 创建测试类

@SpringBootTest
@Log4j2
public class MultipeDataSourceApplicationTests {
@Autowired
private UserService userService;
@Test
public void addUserTest(){
//1. 构建对象
User user=new User();
user.setName("周小欢");
user.setAge(22);
user.setSex("女");
user.setDescription("一个非常可爱的女孩纸");
//2. 添加方法
userService.addUser(user);
log.info("添加员工成功");
}

@Test
public void listUserTest(){
List<User> userList=userService.listUser();
userList.forEach(n->log.info(n));
}
@Test
public void addDeptTest(){
//1. 构建对象
Dept dept=new Dept();
dept.setName("信息管理部");
//2. 添加方法
userService.addDept(dept);
log.info("添加部门成功");
}

@Test
public void listDeptTest(){
List<Dept> deptList=userService.listDept();
deptList.forEach(n->log.info(n));
}

/**
* 数据源切换配置
*/
@Test
public void allDataSourceTest(){
addUserTest();
listDeptTest();
addDeptTest();
listUserTest();
}

}

二.七.二 测试数据源

数据库源1

添加

多数据源配置Jpa(十六)_spring_05

查询

多数据源配置Jpa(十六)_spring_06

数据库 springboot 的 user 表里面,也只存储了这一条数据

多数据源配置Jpa(十六)_spring boot_07

数据库源2

添加

多数据源配置Jpa(十六)_数据库_08

查询

多数据源配置Jpa(十六)_spring boot_09

数据库 springboot2 的 dept 表里面,也只存储了这一条数据

多数据源配置Jpa(十六)_spring boot_10

数据源切换配置 测试

多数据源配置Jpa(十六)_数据库_11

再次查询数据库表

多数据源配置Jpa(十六)_spring_12

多数据源配置Jpa(十六)_spring boot_13

数据源切换配置成功.

本章节的代码放置在 github 上:

​https://github.com/yuejianli/springboot/tree/develop/MultipeDataSource_Jpa​

谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!