微服务推崇单服务单数据库;但是还是免不了存在一个微服务连接多个数据库的情况,今天介绍一下如何使用 JPA 的多数据源。主要采用将不同数据库的 Repository 接口分别存放到不同的 package,Spring 去扫描不同的包,注入不同的数据源来实现多数据源。
学生表 t_student
CREATE TABLE `t_student` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`user_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`sex` int(1) NULL DEFAULT NULL ,
`grade` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
AUTO_INCREMENT=1 ROW_FORMAT=DYNAMIC;
教师表 t_teacher
CREATE TABLE `t_teacher` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`user_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`sex` int(1) NULL DEFAULT NULL ,
`office` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
AUTO_INCREMENT=1 ROW_FORMAT=DYNAMIC;
4.0.0
com.olive
jpa-multip-datasource
0.0.1-SNAPSHOT
jar
jpa-multip-datasource
http://maven.apache.org
org.springframework.boot
spring-boot-starter-parent
2.5.14
UTF-8
8
8
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-data-jpa
mysql
mysql-connector-java
org.projectlombok
lombok
分别为第一个主数据源(primary),第二数据源(second),具体配置如下:
# 基本配置
server:
port: 8080
# 数据库
spring:
jpa:
show-sql: true
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
hibernate:
ddl-auto: update
datasource:
primary:
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/db01?characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true
username: root
password: root
sencond:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/db02?characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true
username: root
password: root
jackson:
serialization:
indent-output: true
DataSourceConfig 配置
/**
* @Description: 数据源配置
*/
@Configuration
public class DataSourceConfig {
@Bean(name = "primaryDataSource")
@Qualifier("primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
@Primary
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondDataSource")
@Qualifier("secondDataSource")
@ConfigurationProperties(prefix = "spring.datasource.sencond")
public DataSource secondDataSource() {
return DataSourceBuilder.create().build();
}
}
PrimaryConfig数据源
/**
* @Description: 主数据源配置
* @date
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryPrimary",
transactionManagerRef = "transactionManagerPrimary",
basePackages = {"com.olive.repository.primary"})
public class PrimaryConfig {
@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@Autowired
private HibernateProperties hibernateProperties;
@Autowired
private JpaProperties jpaProperties;
@Primary
@Bean(name = "entityManagerPrimary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
}
@Primary
@Bean(name = "entityManagerFactoryPrimary") //primary实体工厂
public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
return builder.dataSource(primaryDataSource)
.properties(getHibernateProperties())
.packages("com.olive.entity.primary") //换成你自己的实体类所在位置
.persistenceUnit("primaryPersistenceUnit")
.build();
}
@Primary
@Bean(name = "transactionManagerPrimary")
public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
private Map getHibernateProperties() {
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
}
SecondConfig 数据源源
/**
* @Description: 第二个数据源配置
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactorySecond",
transactionManagerRef = "transactionManagerSecond",
basePackages = {"com.olive.repository.second"})
public class SecondConfig {
@Autowired
@Qualifier("secondDataSource")
private DataSource secondDataSource;
@Resource
private JpaProperties jpaProperties;
@Resource
private HibernateProperties hibernateProperties;
@Bean(name = "entityManagerSecond")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactorySecond(builder).getObject().createEntityManager();
}
@Bean(name = "entityManagerFactorySecond") //primary实体工厂
public LocalContainerEntityManagerFactoryBean entityManagerFactorySecond (EntityManagerFactoryBuilder builder) {
return builder.dataSource(secondDataSource)
.properties(getHibernateProperties())
.packages("com.olive.entity.second") //换成你自己的实体类所在位置
.persistenceUnit("secondaryPersistenceUnit")
.build();
}
@Bean(name = "transactionManagerSecond")
public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactorySecond(builder).getObject());
}
private Map getHibernateProperties() {
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
}
Student实体类
package com.olive.entity.primary;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Data;
@Data
@Entity(name="t_student")
public class StudentDO implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "user_name") // 若实体属性和表字段名称一致时,可以不用加@Column注解
private String name;
@Column(name = "sex")
private int sex;
@Column(name = "grade")
private String grade;
}
Teacher实体类
package com.olive.entity.second;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Data;
@Data
@Entity(name="t_teacher")
public class TeacherDO implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "user_name") // 若实体属性和表字段名称一致时,可以不用加@Column注解
private String name;
@Column(name = "sex")
private int sex;
@Column(name = "office")
private String office;
}
StudentRepository类
package com.olive.repository.primary;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.olive.entity.primary.StudentDO;
@Repository
public interface StudentRepository extends JpaRepository {
}
TeacherRepository类
package com.olive.repository.second;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.olive.entity.second.TeacherDO;
@Repository
public interface TeacherRepository extends JpaRepository {
}
package com.olive;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
package com.olive;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.olive.entity.primary.StudentDO;
import com.olive.entity.second.TeacherDO;
import com.olive.repository.primary.StudentRepository;
import com.olive.repository.second.TeacherRepository;
@SpringBootTest
public class JpaTest {
@Autowired
StudentRepository studentRepository;
@Autowired
TeacherRepository teacherRepository;
@Test
public void userSave() {
StudentDO studentDO = new StudentDO();
studentDO.setName("BUG弄潮儿");
studentDO.setSex(1);
studentDO.setGrade("一年级");
studentRepository.save(studentDO);
TeacherDO teacherDO = new TeacherDO();
teacherDO.setName("Java乐园");
teacherDO.setSex(2);
teacherDO.setOffice("语文");
teacherRepository.save(teacherDO);
}
}
记得点「赞」和「在看」↓
爱你们