Spring Boot +JPA怎么配置多数据源?
- 工作小总结
- 时间:2023-06-14 17:49
- 2504人已阅读
简介
有时候,我们需要在项目中配置多数据源。项目框架是SpringBoot+JPA,怎么配置多数据源呢?一、配置文件添加多数据源配置文件中配置多个数据源。如下:server: port: 8841spring: datasource: admin:
🔔🔔🔔好消息!好消息!🔔🔔🔔
有需要的朋友👉:联系凯哥
有时候,我们需要在项目中配置多数据源。项目框架是Spring Boot+JPA,怎么配置多数据源呢?
一、配置文件添加多数据源
配置文件中配置多个数据源。如下:
server: port: 8841 spring: datasource: admin: url: jdbc:sqlite:D:\data\db\back.db driver-class-name: org.sqlite.JDBC username: password: other: url: jdbc:sqlite:D:\data\db\my-test.db driver-class-name: org.sqlite.JDBC jpa: database: mysql show-sql: true hibernate: ddl-auto: update
说明:凯哥使用的是SQLite。MySQL数据库配置类似。如果需要配置的是MySQL多数据源,就改吧改吧。
二、代码添加
2.1:获取数据库配置信息的类
package com.kaigejava.config.datasource; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * @author kaigejava * @description 获取多数据源属性的 * @company kaigejava * @since 2023/6/14 14:41 */ @Component @Data public class DataSourceProperties { /** * admin库相关的数据库配置 */ @Value("${spring.datasource.admin.url}") private String adminUrl; @Value("${spring.datasource.admin.driver-class-name}") private String adminDriverClass; /** * other库相关的配置 */ @Value("${spring.datasource.other.url}") private String otherUrl; @Value("${spring.datasource.other.driver-class-name}") private String otherDriverClass; }
2.2:数据源配置相关的类
package com.kaigejava.config.datasource; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import javax.annotation.Resource; import javax.sql.DataSource; /** * @author kaigejava * @description * @company kaigejava * @since 2023/6/14 17:17 */ @Configuration public class DataSourceConfig { @Resource DataSourceProperties dataSourceProperties; @Bean @ConfigurationProperties("spring.datasource.one") @Primary DataSource dsOne() { return DataSourceBuilder.create() .url(dataSourceProperties.getAdminUrl()) .driverClassName(dataSourceProperties.getAdminDriverClass()) .build(); } @Bean @ConfigurationProperties("spring.datasource.two") DataSource dsTwo() { return DataSourceBuilder.create() .url(dataSourceProperties.getOtherUrl()) .driverClassName(dataSourceProperties.getOtherDriverClass()) .build(); } }
2.3:配置Admin数据库相关的数据源
package com.kaigejava.config.datasource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; 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 javax.annotation.Resource; import javax.sql.DataSource; /** * @author 凯哥Java * @description admin数据源 * @company kaigejava * @since 2023/6/14 15:29 */ @Configuration @EnableJpaRepositories(basePackages = "com.kaigejava.adminjpa", entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanOne", transactionManagerRef = "transactionManagerOne") public class AdminDataSourceConfig { @Resource DataSourceProperties dataSourceProperties; @Autowired @Qualifier("dsOne") DataSource dsOne; @Autowired JpaProperties jpaProperties; @Bean @Primary LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanOne(EntityManagerFactoryBuilder builder) { return builder.dataSource(dsOne) .packages("com.kaigejava.adminjpa") .properties(jpaProperties.getProperties()) .persistenceUnit("pu1") .build(); } @Bean @Primary PlatformTransactionManager transactionManagerOne(EntityManagerFactoryBuilder builder) { return new JpaTransactionManager(localContainerEntityManagerFactoryBeanOne(builder).getObject()); } }
需要注意:admin是主数据源。所以需要使用@Primary注解标注
2.4:配置另外一个数据库的数据源信息
package com.kaigejava.config.datasource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.boot.jdbc.DataSourceBuilder; 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 javax.annotation.Resource; import javax.sql.DataSource; /** * @author 凯哥Java * @description admin数据源 * @company kaigejava * @since 2023/6/14 15:29 */ @Configuration @EnableJpaRepositories(basePackages = "com.kaigejava.bussiness",entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanTwo",transactionManagerRef = "transactionManagerTwo") public class OtherDataSourceConfig { @Resource DataSourceProperties dataSourceProperties; @Autowired @Qualifier("dsTwo") DataSource dsTwo; @Autowired JpaProperties jpaProperties; @Bean LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanTwo(EntityManagerFactoryBuilder builder) { return builder.dataSource(dsTwo) .packages("com.kaigejava.bussiness") .properties(jpaProperties.getProperties()) .persistenceUnit("pu2") .build(); } @Bean PlatformTransactionManager transactionManagerTwo(EntityManagerFactoryBuilder builder) { return new JpaTransactionManager(localContainerEntityManagerFactoryBeanTwo(builder).getObject()); } }
三:测试类
package com.kaigejava.bussiness.tstudenttest.controller; import com.kaigejava.bussiness.tstudenttest.entity.StudentJpaEntity; import com.kaigejava.bussiness.tstudenttest.service.IStudentJpaService; import com.kaigejava.adminjpa.project.entity.ProjectJpaEntity; import com.kaigejava.adminjpa.project.service.ProjectJpaService; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; /** * @author 凯哥Java * @description * @company 凯哥Java * @since 2023/6/14 15:53 */ @RestController @RequestMapping("/student-test") public class StudentController { //other数据库的 @Resource private IStudentJpaService studentJpaService; //admin数据库的 @Resource private ProjectJpaService projectJpaService; //向other数据库添加数据 @RequestMapping(value = "/save", method = RequestMethod.POST) public StudentJpaEntity save(@RequestBody StudentJpaEntity paramaVo) { return studentJpaService.saveInfo(paramaVo); } //访问other数据库的 @RequestMapping(value = "/get/{id}", method = RequestMethod.GET) public StudentJpaEntity get(@PathVariable("id") Integer id) { return studentJpaService.findInfoById(id); } //访问admin数据库的 @RequestMapping(value = "/getProject/{id}", method = RequestMethod.GET) public ProjectJpaEntity getProject(@PathVariable("id") Integer id) { return projectJpaService.findById(id); } }
通过接口调用,向other数据库中添加数据
运行结果:
同样方法,测试从admin库中获取数据,也正常。
至此,Spring Boot +JPA配置多数据源就完成了。
填坑:
这里最终要的一个坑是:Hibernate中的数据库方言配置,很多博文都没有此步,导致不同类型的数据库连接时依然用同一种数据库方言
org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
此日志就是数据库方言的内容,两个数据源都会加载各自的数据库方言。