前言
之前的文章讲过Spring Boot整合多数据源中用到了JdbcTemplate或Mybatis,本文中我们将使用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。完整依赖如下:
<dependencies>
<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>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
</dependencies>
基本配置
在基本配置中,我们首先来配置多数据源基本信息以及DataSource,首先在application.properties中添加如下配置信息:
# 数据源一
spring.datasource.one.username=root
spring.datasource.one.password=1234
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=1234
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 = "com.yjn.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("com.yjn.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 = "com.yjn.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("com.yjn.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 com.yjn.jpa.dao;
import com.yjn.jpa.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface UserDao extends JpaRepository<User,Integer> {
}
数据源二的dao如下:
package com.yjn.jpa.dao2;
import com.yjn.jpa.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface UserDao2 extends JpaRepository<User,Integer> {
}
共同的实体类如下:
package com.yjn.jpa.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity(name = "t_user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String username;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", age=" + age +
'}';
}
}
到此,所有的配置就算完成了,接下来就可以在Test中注入不同的UserDao,不同的UserDao操作不同的数据源。
@RunWith(SpringRunner.class)
@SpringBootTest
public class JpaApplicationTests {
@Autowired
UserDao userDao;
@Autowired
UserDao2 userDao2;
@Test
public void contextLoads() {
List<User> userList=userDao.findAll();
System.out.println(userList);
List<User> userList2=userDao2.findAll();
System.out.println(userList2);
}
}
来源:https://blog.csdn.net/yjn1995/article/details/99213561