本指南将引导您了解如何使用 Spring Data JPA 在 Spring Boot 应用程序中配置多个数据源。有时需要将应用程序连接到多个数据库(数据源)并根据请求执行操作。
在这种情况下,Spring 框架的灵活性就体现出来了。
在本教程中,我们将创建一个全新的 Spring Boot 应用程序,添加所需的依赖项,使用多个数据源(数据库)对其进行配置,公开 REST 端点并执行操作。
例如,我们有两个不同的数据库,即保存学校信息的 schooldb 和保存学生信息的 studentdb。
1.1 API – http://localhost:8080/school 从 schooldb 数据源获取学校的记录。
[
{
"id": 2,
"name": "BHU",
"address": "Lanka, Varanasi"
}
]
1.2 API – http://localhost:8080/student 从 studentdb 数据源获取学生的记录。
[
{
"id": 1,
"name": "Pallavi",
"age": 30
},
{
"id": 2,
"name": "Sunandana",
"age": 27
}
]
这是 pom.xml 文件,包括此项目中使用的所需依赖项。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>org.websparrow</groupId>
<artifactId>spring-boot-multiple-datasource</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<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.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
我们在 STS 4 IDE 中的应用程序的最终项目结构如下所示:
将在 application.properties 文件中为两个数据源(即 schooldb 和 studentdb)配置数据库(数据源)连接字符串。
application.properties
# MySQL database connection strings for SCHOOL
school.datasource.url=jdbc:mysql://localhost:3306/schooldb?createDatabaseIfNotExist=true
school.datasource.username=root
school.datasource.password=root
# MySQL database connection strings for STUDENT
student.datasource.url=jdbc:mysql://localhost:3306/studentdb?createDatabaseIfNotExist=true
student.datasource.username=root
student.datasource.password=root
# JPA property settings
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.jpa.database=mysql
默认情况下,Spring Boot 将使用前缀为 spring.datasource./*
的配置属性实例化其默认数据源
首先——让我们创建两个简单的实体——每个实体都位于一个单独的数据库中。
Student.java
package org.websparrow.entity.student;
@Entity
@Table(name = "student")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private int age;
// Generate Getters and Setters...
}
School.java
package org.websparrow.entity.school;
@Entity
@Table(name = "school")
public class School {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String address;
// Generate Getters and Setters...
}
由于我们已经创建了两个实体,现在我们必须告诉 Spring 哪个实体属于哪个数据源。这可以通过两种方式进行配置:
1. 在 @Table
注释中设置架构属性。
@Entity
@Table(name = "student", schema = "studentdb")
public class Student {
....
}
2. 在创建 EntityManagerFactoryBuilder
时设置包(在下一步中解释)。
由于我们有两个不同的数据源(数据库),因此需要为这两个数据源创建两个不同的 bean。并确保通过使用 @Primary
注释将一个 bean 作为主要数据源。
// creates data-source properties bean with student database details
@Bean
@Primary
@ConfigurationProperties(prefix = "student.datasource")
public DataSourceProperties studentDataSourceProperties() {
return new DataSourceProperties();
}
// creates data-source bean
@Bean
@Primary
public DataSource studentDataSource() {
return studentDataSourceProperties().initializeDataSourceBuilder()
.type(BasicDataSource.class).build();
}
如果我们未能将一个数据源设为主要数据源,应用程序将无法启动。
@Bean
@ConfigurationProperties(prefix = "school.datasource")
public DataSourceProperties schoolDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
public DataSource schoolDataSource() {
return schoolDataSourceProperties().initializeDataSourceBuilder()
.type(BasicDataSource.class).build();
}
为数据源创建 EnttityManager
bean。我们将使用 EntityManagerFactory
bean 来获取与 JPA 实体交互的 EntityManager
实例。
//creates entity manager with scanned entity classes of student database
@Bean(name = "studentEntityManager")
@Primary
public LocalContainerEntityManagerFactoryBean studentEntityManager(
EntityManagerFactoryBuilder builder) {
return builder.dataSource(studentDataSource()).packages(Student.class)
.build();
}
//creates entity manager with scanned entity classes of school database
@Bean(name = "schoolEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean schoolEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder.dataSource(schoolDataSource()).packages(School.class)
.build();
}
如您所见,我们已经在 packages(School.*class*)
方法中传递了我们的实体。
现在我们将为两个数据源创建 TransactionManager
,我们将使用 @Qualifier 注释将特定的实体管理器自动连接到特定的数据源事务管理器。
// Transaction Manager for Student
@Bean(name = "studentTransactionManager")
@Primary
public PlatformTransactionManager studentTransactionManager(
@Qualifier("studentEntityManager") LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
return new JpaTransactionManager(entityManagerFactoryBean.getObject());
}
// Transaction Manager for School
@Bean(name = "schoolTransactionManager")
public PlatformTransactionManager schoolTransactionManager(
@Qualifier("schoolEntityManagerFactory") LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
return new JpaTransactionManager(entityManagerFactoryBean.getObject());
}
使用 @EnableJPARepositories
注释配置我们的 JPA 存储库。使用此注释,我们将为每个数据源指定以下属性:
basePackages
:该属性包含数据源下的所有存储库。entityManagerFactoryRef
:该属性包含实体管理器的 bean 名称。transactionManagerRef
:该属性包含事务管理器的 bean 名称。@EnableJpaRepositories(
basePackages = "org.websparrow.repository.school",
entityManagerFactoryRef = "schoolEntityManagerFactory",
transactionManagerRef = "schoolTransactionManager"
)
最终的存储库配置文件如下所示。我们为每个数据源创建了不同的存储库配置。
StudentRepositoryConfiguration.java
package org.websparrow.config;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
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 org.websparrow.entity.student.Student;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "org.websparrow.repository.student",
entityManagerFactoryRef = "studentEntityManager",
transactionManagerRef = "studentTransactionManager"
)
public class StudentRepositoryConfiguration {
// creates data-source properties bean with student database details
@Bean
@Primary
@ConfigurationProperties(prefix = "student.datasource")
public DataSourceProperties studentDataSourceProperties() {
return new DataSourceProperties();
}
// creates data-source bean
@Bean
@Primary
public DataSource studentDataSource() {
return studentDataSourceProperties().initializeDataSourceBuilder()
.type(BasicDataSource.class).build();
}
// creates entity manager with scanned entity classes of student database
@Bean(name = "studentEntityManager")
@Primary
public LocalContainerEntityManagerFactoryBean studentEntityManager(
EntityManagerFactoryBuilder builder) {
return builder.dataSource(studentDataSource()).packages(Student.class)
.build();
}
@Bean(name = "studentTransactionManager")
@Primary
public PlatformTransactionManager studentTransactionManager(
@Qualifier("studentEntityManager") LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
return new JpaTransactionManager(entityManagerFactoryBean.getObject());
}
}
SchoolRepositoryConfiguration.java
package org.websparrow.config;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
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 org.websparrow.entity.school.School;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "org.websparrow.repository.school",
entityManagerFactoryRef = "schoolEntityManagerFactory",
transactionManagerRef = "schoolTransactionManager"
)
public class SchoolRepositoryConfiguration {
@Bean
@ConfigurationProperties(prefix = "school.datasource")
public DataSourceProperties schoolDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
public DataSource schoolDataSource() {
return schoolDataSourceProperties().initializeDataSourceBuilder()
.type(BasicDataSource.class).build();
}
@Bean(name = "schoolEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean schoolEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder.dataSource(schoolDataSource()).packages(School.class)
.build();
}
@Bean(name = "schoolTransactionManager")
public PlatformTransactionManager schoolTransactionManager(
@Qualifier("schoolEntityManagerFactory") LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
return new JpaTransactionManager(entityManagerFactoryBean.getObject());
}
}
两个实体的存储库接口。
StudentRepository.java
package org.websparrow.repository.student;
@Repository
public interface StudentRepository
extends JpaRepository<Student, Integer> {
}
SchoolRepository.java
package org.websparrow.repository.school;
@Repository
public interface SchoolRepository extends JpaRepository<School, Integer> {
}
MainController
类为应用程序用户公开 REST 端点。在这个控制器类中,我们创建了 2 个不同的 REST 端点,如下所示:
http://localhost:8080/school:从schooldb数据源中检索记录。
http://localhost:8080/student:将从studentdb数据源中检索记录。
MainController.java
package org.websparrow.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.websparrow.entity.school.School;
import org.websparrow.entity.student.Student;
import org.websparrow.repository.school.SchoolRepository;
import org.websparrow.repository.student.StudentRepository;
@RestController
public class MainController {
@Autowired
private SchoolRepository schoolRepository;
@Autowired
private StudentRepository studentRepository;
@GetMapping(value = "school")
public ResponseEntity<List<School>> getSchool() {
return ResponseEntity.status(HttpStatus.ACCEPTED)
.body(schoolRepository.findAll());
}
@GetMapping(value = "student")
public ResponseEntity<List<Student>> getStudent() {
return ResponseEntity.status(HttpStatus.ACCEPTED)
.body(studentRepository.findAll());
}
}
MultipleDataSourceApplication
类包含主要方法并负责启动应用程序。
MultipleDataSourceApplication.java
package org.websparrow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MultipleDataSourceApplication {
public static void main(String[] args) {
SpringApplication.run(MultipleDataSourceApplication.class, args);
}
}
要测试应用程序,请通过执行上述类来启动 Spring Boot 应用程序,并一一点击以下 API:
**1.**http://localhost:8080/school
它将从 schooldb 获取数据并返回 JSON,如下所示:
[
{
"id": 1,
"name": "RSMT",
"address": "UP College Campus, Varanasi"
},
{
"id": 2,
"name": "BHU",
"address": "Lanka, Varanasi"
}
]
**2.**http://localhost:8080/student
它将从 studentdb 获取数据并返回 JSON,如下所示:
[
{
"id": 1,
"name": "Pallavi",
"age": 30
},
{
"id": 2,
"name": "Sunandana",
"age": 27
},
{
"id": 3,
"name": "Kumud",
"age": 25
}
]
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.websparrow.org/spring/spring-boot-multiple-data-sources-example-with-spring-jpa
内容来源于网络,如有侵权,请联系作者删除!