來(lái)源:haihui_yang 發(fā)布時(shí)間:2018-12-08 11:41:04 閱讀量:1316
SpringBoot 多數(shù)據(jù)源配置
最近在項(xiàng)目中需要連兩個(gè) mysql 數(shù)據(jù)庫(kù),即需要配置多數(shù)據(jù)源。
關(guān)于多數(shù)據(jù)源的配置網(wǎng)上還是有一大堆資料的,在搜尋一番過(guò)后,開(kāi)始進(jìn)行配置。雖然配置過(guò)程中也遇到過(guò)一些坑,但總體上還算比較簡(jiǎn)單。
大體步驟如下:(文末附有項(xiàng)目 github 地址)
一、application.yml 中添加數(shù)據(jù)庫(kù)配置(兩個(gè)數(shù)據(jù)庫(kù),分別為:primary、secondary)
spring:
datasource:
primary:
hikari:
driver-class-name: com.mysql.cj.jdbc.Driver
connection-test-query: SELECT 1 FROM DUAL
minimum-idle: 1
maximum-pool-size: 5
pool-name: bosPoolName
max-lifetime: 180000000
jdbcUrl: jdbc:mysql://${mysqlHost1:localhost}:3306/test1?useSSL=false&useUnicode=true&characterEncoding=UTF-8
username: ${mysqlUsername1:root}
password: ${mysqlPassword1:123456}
secondary:
hikari:
driver-class-name: com.mysql.cj.jdbc.Driver
connection-test-query: SELECT 1 FROM DUAL
minimum-idle: 1
maximum-pool-size: 5
pool-name: bosPoolName
max-lifetime: 180000000
jdbcUrl: jdbc:mysql://${mysqlHost2:localhost}:3306/test2?useSSL=false&useUnicode=true&characterEncoding=UTF-8
username: ${mysqlUsername2:root}
password: ${mysqlPassword2:123456}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
二、添加 PrimaryDataSourceConfig 和 SecondaryDataSourceConfig 配置類(lèi)
PrimaryDataSourceConfig.java
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "primaryEntityManagerFactory",
transactionManagerRef = "primaryTransactionManager",
basePackages = {"com.yhh.primary.**.dao"}//primary數(shù)據(jù)庫(kù)對(duì)應(yīng)dao所在的package
)
public class PrimaryDataSourceConfig {
@Bean(name = "primaryDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary.hikari")//primary數(shù)據(jù)庫(kù)配置
public DataSource getDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Primary
@Bean
public JdbcTemplate getJdbcTemplate() {
return new JdbcTemplate(getDataSource());
}
@Primary
@Bean(name = "primaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
@Qualifier("vendorProperties") Map<String, ?> vendorProperties) {//自己定義的Bean:vendorProperties
return builder
.dataSource(getDataSource())
.properties(vendorProperties)
.packages("com.yhh.primary.**.entity")//primary數(shù)據(jù)庫(kù)對(duì)應(yīng)entity所在的package
.persistenceUnit("primary")//persistence unit,隨便給,須唯一
.build();
}
@Primary
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("primaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
SecondaryDataSourceConfig.java
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "secondaryEntityManagerFactory",
transactionManagerRef = "secondaryTransactionManager",
basePackages = "com.yhh.secondary.**.dao"//secondary數(shù)據(jù)庫(kù)對(duì)應(yīng)dao所在的package
)
public class SecondaryDataSourceConfig {
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary.hikari")//secondary數(shù)據(jù)庫(kù)配置
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean(name = "secondaryJdbcTemplate")
public JdbcTemplate secondaryJdbcTemplate() {
return new JdbcTemplate(secondaryDataSource());
}
@Bean(name = "secondaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
@Qualifier("vendorProperties") Map<String, ?> vendorProperties) {//自己定義的Bean:vendorProperties
return builder
.dataSource(secondaryDataSource())
.properties(vendorProperties)
.packages("com.yhh.secondary.**.entity")//secondary數(shù)據(jù)庫(kù)對(duì)應(yīng)entity所在的package
.persistenceUnit("secondary")//persistence unit,隨便給,須唯一
.build();
}
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory entityManagerFactory
) {
return new JpaTransactionManager(entityManagerFactory);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
三、vendorProperties Bean 配置
@Autowired
private JpaProperties jpaProperties;
@Bean(name = "vendorProperties")
public Map<String, Object> getVendorProperties() {
return jpaProperties.getHibernateProperties(new HibernateSettings());
}
1
2
3
4
5
6
7
實(shí)際上這里配置的是下面這三個(gè)屬性:
"hibernate.id.new_generator_mappings" -> "true"
1
"hibernate.physical_naming_strategy" -> "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy"
1
"hibernate.implicit_naming_strategy" -> "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy"
1
文末有兩個(gè)參考鏈接,按照這兩個(gè)鏈接基本上就可以將其配置出來(lái),不過(guò)當(dāng)數(shù)據(jù)庫(kù)字段名命名規(guī)則為下劃線命名法時(shí)會(huì)有問(wèn)題。異常如下:
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1054, SQLState: 42S22
o.h.engine.jdbc.spi.SqlExceptionHelper : Unknown column 'teacherdo0_.teacherName' in 'field list'
1
2
原因是代碼中是駝峰命名法,而數(shù)據(jù)庫(kù)中命名是下劃線命名法,二者無(wú)法相互映射,會(huì)報(bào) Unknown column 異常。當(dāng)時(shí)為這個(gè)問(wèn)題找了好半天,后來(lái)通過(guò)添加 vendorProperties 解決。
四、添加 entity 及 dao (需要注意的是:entity 與 dao 的 package 位置須與前面配置一致)
StudentDO.java
package com.yhh.primary.entity;
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
@Table(name = "student")
public class StudentDO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String studentName;
private Integer age;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
StudentDao.java
package com.yhh.primary.dao;
import com.yhh.primary.entity.StudentDO;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentDao extends JpaRepository<StudentDO, Integer> {
}
1
2
3
4
5
6
7
8
9
10
TeacherDO.java
package com.yhh.secondary.entity;
import lombok.Data;
import javax.persistence.*;
@Entity
@Data
@Table(name = "teacher")
public class TeacherDO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String teacherName;
private Integer age;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
TeacherDao.java
package com.yhh.secondary.dao;
import com.yhh.secondary.entity.TeacherDO;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface TeacherDao extends JpaRepository<TeacherDO, Integer> {
}
1
2
3
4
5
6
7
8
9
10
五、測(cè)試與驗(yàn)證(需要數(shù)據(jù)庫(kù)有與之對(duì)應(yīng)的 table 及數(shù)據(jù),在 github 項(xiàng)目的 README 文件中有現(xiàn)成的 sql 語(yǔ)句)
可以通過(guò)添加 IT 或 Controller 的方式驗(yàn)證是否配置成功。
1、IT (集成測(cè)試),跑集成測(cè)試,兩個(gè) dao 都可以查出數(shù)據(jù)。
package com.yhh.dao;
import com.yhh.primary.dao.StudentDao;
import com.yhh.primary.entity.StudentDO;
import com.yhh.secondary.dao.TeacherDao;
import com.yhh.secondary.entity.TeacherDO;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
@EnableAutoConfiguration
public class MutiDaoIT {
@Autowired
private StudentDao studentDao;
@Autowired
private TeacherDao teacherDao;
@Test
public void muti_dao_IT() {
List<TeacherDO> teacherDOList = teacherDao.findAll();
List<StudentDO> studentDOList = studentDao.findAll();
Assert.assertFalse(teacherDOList.isEmpty());
Assert.assertFalse(studentDOList.isEmpty());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2、Controller,通過(guò)啟動(dòng) SpringBoot 應(yīng)用,請(qǐng)求 http://localhost:8888/api/muti-data 會(huì)得到一個(gè) json 數(shù)組,里面有四條數(shù)據(jù)。
package com.yhh.rest;
import com.yhh.primary.dao.StudentDao;
import com.yhh.secondary.dao.TeacherDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.ArrayList;
import java.util.List;
@Controller
@RequestMapping(value = "/api")
@Slf4j
public class ShowController {
private final StudentDao studentDao;
private final TeacherDao teacherDao;
public ShowController(StudentDao studentDao, TeacherDao teacherDao) {
this.studentDao = studentDao;
this.teacherDao = teacherDao;
}
@GetMapping(value = "/muti-data")
public ResponseEntity queryMutiData() {
log.info("query muti-data.");
List result = new ArrayList<>();
result.addAll(studentDao.findAll());
result.addAll(teacherDao.findAll());
log.info("result size is {}.", result.size());
return ResponseEntity.ok(result);
}
}
---------------------
在線
客服
服務(wù)時(shí)間:周一至周日 08:30-18:00
選擇下列產(chǎn)品馬上在線溝通:
客服
熱線
7*24小時(shí)客服服務(wù)熱線
關(guān)注
微信
關(guān)注官方微信