springboot Jpa多数据源(不同库)配置过程
作者:Mr-Wanter
这篇文章主要介绍了springboot Jpa多数据源(不同库)配置过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
一、前言
springboot版本不同对多数据源配置代码有一定影响,部分方法和配置略有不同。
本文采用的springboot版本为2.3.12,数据源为mysql和postgresql
二、配置实战
2.1 基础pom
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.21</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> </dependencies>
2.2 配置文件
spring.datasource.mysql.jdbc-url=jdbc:mysql://localhost:3306/heilongjiang?characterEncoding=UTF-8&useSSL=false&useTimezone=true&serverTimezone=GMT%2B8 spring.datasource.mysql.driver-class-name=com.mysql.jdbc.Driver spring.datasource.mysql.username=root spring.datasource.mysql.password=123456 spring.datasource.pg.jdbc-url=jdbc:postgresql://localhost:5432/hljsyjt?useUnicode=true&characterEncoding=utf8¤tSchema=emergencydev,expert,public spring.datasource.pg.driver-class-name=org.postgresql.Driver spring.datasource.pg.username=postgres spring.datasource.pg.password=postgres spring.jpa.properties.hibernate.mysql-dialect=org.hibernate.dialect.MySQLDialect spring.jpa.properties.hibernate.pg-dialect=org.hibernate.dialect.PostgreSQLDialect spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false
2.3 数据源配置类
package com.gsafety.bg.industrial.config; 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.sql.DataSource; /** * @author Mr.wanter * @time 2021-8-11 0011 * @description */ @Configuration public class DataSourceConfig { @Bean("dataSourceMysql") @Primary @ConfigurationProperties(prefix = "spring.datasource.mysql") public DataSource dataSourceMysql() { return DataSourceBuilder.create().build(); } @Bean("dataSourcePg") @ConfigurationProperties(prefix = "spring.datasource.pg") public DataSource dataSourcePg() { return DataSourceBuilder.create().build(); } }
2.4 数据源指定配置类
mysql指定数据源:
package com.gsafety.bg.industrial.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties; import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings; 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 org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; /** * @author Mr.wanter * @time 2021-8-11 0011 * @description */ @Configuration @EnableTransactionManagement @EnableJpaRepositories( entityManagerFactoryRef = "entityManagerFactoryMysql",//配置连接工厂 entityManagerFactory transactionManagerRef = "transactionManagerMysql", //配置 事物管理器 transactionManager basePackages = {"com.gsafety.bg.industrial.dao"}//设置持久层所在位置 ) public class MysqlDataSourceConfig { @Autowired private JpaProperties jpaProperties; @Autowired private HibernateProperties hibernateProperties; // 自动注入配置好的数据源 @Autowired @Qualifier("dataSourceMysql") private DataSource mysqlDataSource; // 获取对应的数据库方言 @Value("${spring.jpa.properties.hibernate.mysql-dialect}") private String mysqlDialect; /** * @param builder * @return */ @Bean(name = "entityManagerFactoryMysql") @Primary public LocalContainerEntityManagerFactoryBean entityManagerFactoryMysql(EntityManagerFactoryBuilder builder) { Map<String, String> map = new HashMap<>(); // 设置对应的数据库方言 map.put("hibernate.dialect", mysqlDialect); jpaProperties.setProperties(map); Map<String, Object> properties = hibernateProperties.determineHibernateProperties( jpaProperties.getProperties(), new HibernateSettings()); return builder //设置数据源 .dataSource(mysqlDataSource) //设置数据源属性 .properties(properties) //设置实体类所在位置.扫描所有带有 @Entity 注解的类 .packages("com.gsafety.bg.industrial.dao.po") // Spring会将EntityManagerFactory注入到Repository之中.有了 EntityManagerFactory之后, // Repository就能用它来创建 EntityManager 了,然后 EntityManager 就可以针对数据库执行操作 .persistenceUnit("mysqlPersistenceUnit") .build(); } /** * 配置事物管理器 * * @param builder * @return */ @Bean(name = "transactionManagerMysql") @Primary PlatformTransactionManager transactionManagerMysql(EntityManagerFactoryBuilder builder) { return new JpaTransactionManager(entityManagerFactoryMysql(builder).getObject()); } }
pg指定数据源:
package com.gsafety.bg.industrial.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties; import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings; 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.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 javax.sql.DataSource; import java.util.HashMap; import java.util.Map; /** * @author Mr.wanter * @time 2021-8-11 0011 * @description */ @Configuration @EnableTransactionManagement @EnableJpaRepositories( entityManagerFactoryRef = "entityManagerFactoryPg",//配置连接工厂 entityManagerFactory transactionManagerRef = "transactionManagerPg", //配置 事物管理器 transactionManager basePackages = {"com.gsafety.bg.data.dao"}//设置持久层所在位置 ) public class PgDataSourceConfig { @Autowired private JpaProperties jpaProperties; @Autowired private HibernateProperties hibernateProperties; //自动注入配置好的数据源 @Autowired @Qualifier("dataSourcePg") private DataSource PgDataSource; // 获取对应的数据库方言 @Value("${spring.jpa.properties.hibernate.pg-dialect}") private String pgDialect; /** * @param builder * @return */ @Bean(name = "entityManagerFactoryPg") public LocalContainerEntityManagerFactoryBean entityManagerFactoryPg(EntityManagerFactoryBuilder builder) { Map<String, String> map = new HashMap<>(); // 设置对应的数据库方言 map.put("hibernate.dialect", pgDialect); jpaProperties.setProperties(map); Map<String, Object> properties = hibernateProperties.determineHibernateProperties( jpaProperties.getProperties(), new HibernateSettings()); return builder //设置数据源 .dataSource(PgDataSource) //设置数据源属性 .properties(properties) //设置实体类所在位置.扫描所有带有 @Entity 注解的类 .packages("com.gsafety.bg.data.dao.po") // Spring会将EntityManagerFactory注入到Repository之中.有了 EntityManagerFactory之后, // Repository就能用它来创建 EntityManager 了,然后 EntityManager 就可以针对数据库执行操作 .persistenceUnit("pgPersistenceUnit") .build(); } /** * 配置事物管理器 * * @param builder * @return */ @Bean(name = "transactionManagerPg") PlatformTransactionManager transactionManagerPg(EntityManagerFactoryBuilder builder) { return new JpaTransactionManager(entityManagerFactoryPg(builder).getObject()); } }
2.5 如何应用
数据源配置类中指定了扫描po和dao包的路径
例如entityManagerFactoryPg中的com.gsafety.bg.data.dao.po和com.gsafety.bg.data.dao
那么我们只需要在指定的包下创建po和dao即可,service包层次不受影响,自定义即可。
三数据源同理即可。
左侧为双数据源(与本篇实战内容一致),右侧为三数据源(三数据源目录结构示例)。
其他编码常规开发即可
- po:
@Entity @Builder @Data @AllArgsConstructor @NoArgsConstructor @Table(name = "jc_repertory") public class JcRepertoryPO implements Serializable { //some fields }
- dao:
public interface JcRepertoryDao extends JpaRepository<JcRepertoryPO, String>, JpaSpecificationExecutor<JcRepertoryPO> { }
- service:
public interface JcRepertoryService { List<JcRepertoryPO> list(); }
@Service public class JcRepertoryServiceImpl implements JcRepertoryService { @Resource private JcRepertoryDao jcRepertoryDao; @Override public List<JcRepertoryPO> list() { List<JcRepertoryPO> all = jcRepertoryDao.findAll(); return all; } }
- controller 略
启动类添加扫描
@SpringBootApplication_(_scanBasePackages = _{_"com.gsafety.bg.data", "com.gsafety.bg.industrial"_})_
三、遇到的问题 数据库连接报错
1.jdbcUrl is required with driverClassName
- 主要原因是在1.0 配置数据源的过程中主要是写成:spring.datasource.url 和spring.datasource.driverClassName。
- 而在2.0升级之后需要变更成:spring.datasource.jdbc-url和spring.datasource.driver-class-name
spring.datasource.pg.jdbc-url=jdbc:postgresql://localhost:5432/hljsyjt?useUnicode=true&characterEncoding=utf8¤tSchema=emergencydev,expert,public spring.datasource.pg.driver-class-name=org.postgresql.Driver
2.Paging query needs to have a Pageable parameter!
- 原系统中对jap的Repository进行了封装,采用常规方式调用即可。
3.more than one ‘primary’ bean found among candidates
- 2.4 数据源指定配置类 中只有一个类中的方法添加 @Primary 另外一个不要加这个注解
4.互联网查询的代码中JpaProperties没有getHibernateProperties
- 与springboot版本有关,上面代码已修改。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。