Spring Boot中使用的Jpa实际上是Spring Data Jpa,Spring Data是Spring家族的一个子项目,用于简化SQL和NoSQL的访问。
下面来做一下SpringBoot2.0+Spring Data Jpa实现多数据源。
- 首先,在application.yml 中做一些DataSource的配置,
spring:
application:
name: ms
jackson:
date-format: yyyy-MM-dd HH:mm:ss.SSS
time-zone: GMT+8
datasource:
primary:
type: com.alibaba.druid.pool.DruidDataSource
jdbc-url: jdbc:mysql://localhost:3306/db1?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
username :
password :
driverClassName : com.mysql.cj.jdbc.Driver
secondary:
jdbc-url: jdbc:postgresql://localhost:5432/postgis
username:
password:
driverClassName: org.postgresql.Driver
jpa:
hibernate:
primary-dialect: org.hibernate.dialect.MySQL5Dialect
secondary-dialect: org.hibernate.dialect.PostgreSQL9Dialect
ddl-auto: update
show-sql: true
properties:
hibernate:
temp:
use_jdbc_metadata_defaults: false
use_jdbc_metadata_defaults: false 是为了解决:这个 org.postgresql.jdbc.PgConnection.createClob() 方法尚未被实作。
说明:平常我们配置URL的时候使用spring.datasource.primary.url,但是这里不行了,这么写会报错:jdbcUrl is required with driverClassName。
spring.datasource.url 数据库的 JDBC URL。
spring.datasource.jdbc-url 用来重写自定义连接池
官方文档的解释是:
因为连接池的实际类型没有被公开,所以在您的自定义数据源的元数据中没有生成密钥,而且在IDE中没有完成(因为DataSource接口没有暴露属性)。另外,如果您碰巧在类路径上有Hikari,那么这个基本设置就不起作用了,因为Hikari没有url属性(但是确实有一个jdbcUrl属性)。
因此要改为 spring.datasource.primary.jdbc-url
- 编写DataSourceConfig
import javax.sql.DataSource;
/**
* @create 2019-11-17 12:47
* @desc 配置多数据源
**/
@Configuration
public class DataSourceConfig {
@Bean(name = "primaryDataSource")
@Primary
@Qualifier("primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDatasource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@Qualifier("secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
- 编写PrimaryConfig
/**
* @create 2019-11-17 12:50
* @desc MySQL数据源的配置
**/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactoryPrimary",//配置连接工厂 entityManagerFactory
transactionManagerRef = "transactionManagerPrimary", //配置 事物管理器 transactionManager
basePackages = {"xxx.xxx.xxx.xxx.repo"}//设置持久层所在位置
)
public class PrimaryConfig {
@Autowired
private Properties jpaProperties;
@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;// 自动注入配置好的数据源
/* @Autowired
private HibernateProperties hibernateProperties;*/
@Value("${spring.jpa.hibernate.primary-dialect}")
private String primaryDialect;// 获取对应的数据库方言
@Primary
@Bean(name = "entityManagerPrimary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
}
/**
*
* @param builder
* @return
*/
@Bean(name = "entityManagerFactoryPrimary")
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean entityManagerFactory = builder
//设置数据源
.dataSource(primaryDataSource)
//设置实体类所在位置.扫描所有带有 @Entity 注解的类
.packages("xxx.xxx.xxx.xxx.entity")
// Spring会将EntityManagerFactory注入到Repository之中.有了 EntityManagerFactory之后,
// Repository就能用它来创建 EntityManager 了,然后 EntityManager 就可以针对数据库执行操作
.persistenceUnit("primaryPersistenceUnit")
.build();
entityManagerFactory.setJpaProperties(jpaProperties);
return entityManagerFactory;
}
/**
* 配置事物管理器
*
* @param builder
* @return
*/
@Bean(name = "transactionManagerPrimary")
@Primary
PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
}
- 编写SecondaryConfig
/**
* @create 2019-11-17 13:01
* @desc postgresql 数据源的配置
**/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef="entityManagerFactorySecondary",
transactionManagerRef="transactionManagerSecondary",
basePackages= { "xxx.xxx.xxx.xxx.repo" })
public class SecondaryConfig {
@Autowired
private Properties jpaProperties;
@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondaryDataSource;
/*@Autowired
private HibernateProperties hibernateProperties;*/
@Value("${spring.jpa.hibernate.secondary-dialect}")
private String secondaryDialect;
@Bean(name = "entityManagerSecondary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactorySecondary(builder).getObject().createEntityManager();
}
@Bean(name = "entityManagerFactorySecondary")
public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean entityManagerFactory = builder
.dataSource(secondaryDataSource)
.packages("xxx.xxx.xxx.xxx.entity")
.persistenceUnit("secondaryPersistenceUnit")
.build();
entityManagerFactory.setJpaProperties(jpaProperties);
return entityManagerFactory;
}
/*
private Map getVendorProperties(DataSource dataSource) {
Map map = new HashMap<>();
map.put("hibernate.dialect",secondaryDialect);
jpaProperties.setProperties(map);
return jpaProperties.getHibernateProperties(dataSource);
}*/
//spring boot 2.1以上版本应该这么写 JPA多数据源配置
/*@Bean(name = "entityManagerFactorySecondary")
public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(
EntityManagerFactoryBuilder builder, JpaProperties jpaProperties,
HibernateProperties hibernateProperties) {
Map properties = hibernateProperties.determineHibernateProperties(
jpaProperties.getProperties(), new HibernateSettings());
return builder.dataSource(secondaryDataSource).properties(properties)
.packages("com.jcloud.traffic.situation.postgis.entity").build();
}*/
@Bean(name = "transactionManagerSecondary")
PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
}
}
- 测试,写好相关数据库中对应的entity和repository,写几个service作为测试
/**
* @create 2019-11-16 16:08
* @desc
**/
@RestController
public class DemoController {
@Autowired
private DemoService demoService;
@Autowired
private TestService tstService;
@GetMapping("/test")
public Map te(){
User u = demoService.findByid("17");
List
postman访问接口,查看结果
{
"code": 0,
"message": "",
"data": {
"byId": [
{
"id": 1,
"city": "杭州市",
"date": 1549987200000,
"time": 43557000,
.......
}
],
"user": {
"gid": 787,
"id": 17,
"type": 2,
.......
}
}
}
6.补充一些依赖
org.springframework.boot
spring-boot-starter-test
test
org.projectlombok
lombok
1.16.18
org.springframework
spring-tx
org.springframework.boot
spring-boot-starter-data-jpa
org.postgresql
postgresql
42.2.5
mysql
mysql-connector-java
8.0.12
runtime
org.springframework.boot
spring-boot-autoconfigure
2.0.2.RELEASE
com.alibaba
druid
1.1.13
com.alibaba
druid-spring-boot-starter
1.1.13
log4j
log4j
1.2.17
com.googlecode.log4jdbc
log4jdbc
1.2