SpringBoot - 使用Spring Data JPA操作数据库2(多数据源的配置与使用)
作者:hangge | 2019-11-20 08:10
所谓多数据源,就是一个 Java EE 项目中采用了不同数据库实例中的多个库,或者同一个数据库实例中多个不同的库。JPA 和 MyBatis 配置多数据源类似(点击查看),不同的是,JPA 配置时主要提供不同的 LocalContainerEntityManagerFactoryBean 以及事务管理器,具体配置步骤如下。
三、多数据源的配置与使用
1,添加依赖
首先编辑 pom.xml 文件,添加相关依赖:
注意:跟前文相比,这里的数据库连接池依赖改用 druid-spring-boot-starter。druid-spring-boot-starter 可以帮助开发者在 Spring Boot 项目中轻松集成 Druid 数据库连接池和监控。
<!-- Spring Data JPA 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 数据库驱动依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
2,配置数据库链接
(1)假设我们需要同时连接如下 hangge、hangge2 这两个数据库。

(2)在 application.properties 中配置数据库连接信息,以及 JPA 相关的配置:
注意:这里的 JPA 配置与单独数据库的 JPA 有区别,因为后面的配置中要从 JpaProperties 中的 getProperties 方法中获取所有 JPA 相关的配置,因此这里的属性前缀都是 spring.jpa.properties
# 数据源 1
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.one.url=jdbc:mysql://localhost:3306/hangge
spring.datasource.one.username=root
spring.datasource.one.password=hangge1234
# 数据源 2
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.two.url=jdbc:mysql://localhost:3306/hangge2
spring.datasource.two.username=root
spring.datasource.two.password=hangge1234
#是否在控制台打印JPA执行过程生成的SQL
spring.jpa.properties.show-sql=true
#表示JPA对应的数据库是MySQL
spring.jpa.properties.database=mysql
#表示在项目启动时根据实体类更新数据库中的表
spring.jpa.properties.hibernate.hbm2ddl.auto=update
#表示使用的数据库方言是MySQL57Dialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
3,配置数据源
创建 DataSourceConfig 配置数据源,根据 application.properties 中的配置生成两个数据源:
代码说明:
- DataSourceConfig 中提供了两个数据源:dsOne 和 dsTwo ,默认方法名即为实例名。
- @ConfigurationProperties 注解表示使用不同前缀的配置文件来创建不同的 DataSource 实例。
- 注意:在第一个 DataSource 上还标注了 @Primary 注解。否则程序启动时会报 Parameter 0 of method entityManagerFactoryBeanOne in com.example.demo.config.JpaConfigOne required a bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' that could not be found. 错误
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.one")
@Primary
DataSource dsOne() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.two")
DataSource dsTwo() {
return DruidDataSourceBuilder.create().build();
}
}
4,创建 JPA 配置
(1)接下需要根据两个配置好的数据源创建两个不同的 JPA 配置。第一个 JPA 配置如下:
(1)使用 @EnableTransactionManagement 注解来进行 JPA 的配置,该注解中主要配置了三个属性:
(4)配置类中第二个方法表示创建一个事务管理器。JpaTransactionManager 提供对单个 EntityManagerFactory 的事务支持,专门用于解决 JPA 中的事务管理。
- basePackages 用来指定 Repository 所在的位置。
- entityManagerFactoryRef 用来指定实体类管理工厂 Bean 的名称。
- transactionManagerRef 用来指定事物管理器的引用名称,这里的引用名称就是 JpaConfigOne 类中注册的 Bean 的名称(默认的 Bean 名称为方法名)
- 首先配置数据源
- 然后设置 JPA 相关配置(JpaProperties 由系统自动加载)
- 再设置实体类所在的位置。
- 最后配置持久化单元名。若项目中只有一个 EntityManagerFactory,则 persistenceUnit 可以省略掉,若有多个,则必须明确指定持久化单元名。
(4)配置类中第二个方法表示创建一个事务管理器。JpaTransactionManager 提供对单个 EntityManagerFactory 的事务支持,专门用于解决 JPA 中的事务管理。
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.example.demo.dao1",
entityManagerFactoryRef = "entityManagerFactoryBeanOne",
transactionManagerRef = "platformTransactionManagerOne")
public class JpaConfigOne {
@Resource(name = "dsOne")
DataSource dsOne;
@Autowired
JpaProperties jpaProperties;
@Bean
@Primary
LocalContainerEntityManagerFactoryBean entityManagerFactoryBeanOne(
EntityManagerFactoryBuilder builder) {
return builder.dataSource(dsOne)
.properties(jpaProperties.getProperties())
.packages("com.example.demo.bean")
.persistenceUnit("pu1")
.build();
}
@Bean
PlatformTransactionManager platformTransactionManagerOne(
EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean factoryOne
= entityManagerFactoryBeanOne(builder);
return new JpaTransactionManager(factoryOne.getObject());
}
}
(2)第二个 JPA 配置如下:
JpaConfigTwo 的配置与 JpaConfigOne 类似,主要区别在于 LocalContainerEntityManagerFactoryBean 实例不需要添加 @Primary 注解。
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.example.demo.dao2",
entityManagerFactoryRef = "entityManagerFactoryBeanTwo",
transactionManagerRef = "platformTransactionManagerTwo")
public class JpaConfigTwo {
@Resource(name = "dsTwo")
DataSource dsTwo;
@Autowired
JpaProperties jpaProperties;
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactoryBeanTwo(
EntityManagerFactoryBuilder builder) {
return builder.dataSource(dsTwo)
.properties(jpaProperties.getProperties())
.packages("com.example.demo.bean")
.persistenceUnit("pu2")
.build();
}
@Bean
PlatformTransactionManager platformTransactionManagerTwo(
EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean factoryTwo
= entityManagerFactoryBeanTwo(builder);
return new JpaTransactionManager(factoryTwo.getObject());
}
}
5,创建 Repository(数据库访问层)
根据上面第 4 步的配置,我们分别在 com.example.demo.dao1 和 com.example.demo.dao2 包下创建两个 Repository,分别用于操作不同的数据源。
- BookDao1 内容如下:
package com.example.demo.dao1;
import com.example.demo.bean.Book;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BookDao1 extends JpaRepository<Book, Integer> {
}
- BookDao2 内容如下:
package com.example.demo.dao2;
import com.example.demo.bean.Book;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BookDao2 extends JpaRepository<Book, Integer> {
}
6,创建 Controller
为方便演示,这里省略了 Service 层,将 BookDao1、BookDao2 直接注入到 Controller 中使用:分别向两个数据库中各插入一条数据。@RestController
public class HelloController {
@Autowired
BookDao1 bookDao1;
@Autowired
BookDao2 bookDao2;
@RequestMapping("/test")
public void test() {
// 往第一个数据库中插入数据
Book book1 = new Book();
book1.setName("时间的秩序");
book1.setAuthor("卡洛·罗韦利");
book1.setPrice(56f);
bookDao1.save(book1); //使用save方法将数据保存到数据库
// 往第二个数据库中插入数据
Book book2 = new Book();
book2.setName("发条橙");
book2.setAuthor("安东尼·伯吉斯 ");
book2.setPrice(22f);
bookDao2.save(book2); //使用save方法将数据保存到数据库
}
7,运行测试
在浏览器中访问 http://localhost:8080/test 地址,可以看到两个数据库中的表和数据都已经存在了。

全部评论(0)