spring+Jpa多數(shù)據(jù)源配置的方法示例
今天臨下班時(shí)遇到了一個(gè)需求,我的管理平臺(tái)需要從不同的數(shù)據(jù)庫中獲取數(shù)據(jù)信息,這就需要進(jìn)行Spring的多數(shù)據(jù)源配置,對于這種配置,第一次永遠(yuǎn)都是痛苦的,不過經(jīng)歷了這次的折磨,今后肯定會(huì)對這種配置印象深刻。我們這里簡單回顧一下流程。
我們配置了兩個(gè)數(shù)據(jù)庫,一個(gè)是公司的數(shù)據(jù)庫,另一個(gè)是我本地的一個(gè)數(shù)據(jù)庫。首先是application.yml的配置(其中對于公司的數(shù)據(jù)庫我們采取了假的地址,而本機(jī)的數(shù)據(jù)庫是真是存在對應(yīng)的表和庫的)
數(shù)據(jù)庫信息:

數(shù)據(jù)表信息:

1、application.yml
datasource: primary: url: jdbc:mysql://companyurl.com:5002/db1 username: unameq password: passwd1 driver-class-name: com.mysql.jdbc.Driver secondary: url: jdbc:mysql://localhost:3306/django_test username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver jpa: database-platform: org.hibernate.dialect.MySQL5Dialect hibernate: ddl-auto: update show-sql: true
2、創(chuàng)建總的DataSource配置文件以及兩個(gè)Repostory的配置文件PrimaryConfig以及SecondaryConfig
DataSourceConfig
@Configuration
public class DataSourceConfig {
@Bean(name = "primaryDataSource")
@Qualifier("primaryDataSource")
@ConfigurationProperties(prefix="spring.datasource.primary")//對應(yīng)的數(shù)據(jù)庫配置信息
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@Qualifier("secondaryDataSource")
@Primary
@ConfigurationProperties(prefix="spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
PrimaryConfig
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef="entityManagerFactoryPrimary",
transactionManagerRef="transactionManagerPrimary",
basePackages= { "數(shù)據(jù)訪問層所在的包" }) //設(shè)置Repository所在位置
public class PrimaryConfig {
@Autowired @Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@Primary
@Bean(name = "entityManagerPrimary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
}
@Primary
@Bean(name = "entityManagerFactoryPrimary")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
return builder
.dataSource(primaryDataSource)
.properties(getVendorProperties(primaryDataSource))
.packages("實(shí)體類所在的包") //設(shè)置實(shí)體類所在位置
.persistenceUnit("primaryPersistenceUnit")
.build();
}
@Autowired
private JpaProperties jpaProperties;
private Map<String, String> getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}
@Primary
@Bean(name = "transactionManagerPrimary")
public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
}
SecondaryConfig
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef="entityManagerFactorySecondary",
transactionManagerRef="transactionManagerSecondary",
basePackages= { "數(shù)據(jù)訪問層所在的包" }) //設(shè)置Repository所在位置
public class SecondaryConfig {
@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondaryDataSource;
@Bean(name = "entityManagerSecondary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactorySecondary(builder).getObject().createEntityManager();
}
@Bean(name = "entityManagerFactorySecondary")
public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(secondaryDataSource)
.properties(getVendorProperties(secondaryDataSource))
.packages("實(shí)體類所在的包") //設(shè)置實(shí)體類所在位置
.persistenceUnit("secondaryPersistenceUnit")
.build();
}
@Autowired
private JpaProperties jpaProperties;
private Map<String, String> getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}
@Bean(name = "transactionManagerSecondary")
PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
}
}
3、然后我對于本地?cái)?shù)據(jù)庫新建實(shí)體類PeoplePerson
@Entity
@Table(name = "people_person")
public class PeoplePerson implements Serializable {
@Id
@GeneratedValue
private Integer id;
@Column(name = "name")
private String name;
@Column(name = "age")
private Integer age;
public PeoplePerson() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "PeoplePerson{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
并創(chuàng)建對應(yīng)的Repositoy,PeoplePersonDao并創(chuàng)建了一個(gè)findAll的方法
@Transactional@Repositorypublic interface PeoplePersonDao extends JpaRepository<PeoplePerson, Long>
{
List<PeoplePerson> findAll();
}
4、最后,在test包中進(jìn)行測試
@Autowired
private PeoplePersonDao peoplePersonDao;
@Test
public void testMultiDataSource() {
List<PeoplePerson> list = peoplePersonDao.findAll();
for (int i = 0; i < list.size(); i++) {
logger.info(list.get(i).toString());
}
}
測試結(jié)果

一些坑
不僅僅是dao層掃描的包需要區(qū)分,對于實(shí)體類所在的包,不同的DataSource的配置中也需要區(qū)分開
對于這種套路性的東西,總結(jié)一遍是非常必要的,下次可以節(jié)省許多不必要的時(shí)間,對于內(nèi)部原理,我將在完成對Ioc和Aop分析后反過來分析其原理。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
idea遠(yuǎn)程Debug部署在服務(wù)器上的服務(wù)
在開發(fā)的時(shí)候我們通常在本地代碼上debug程序,但是服務(wù)部署到了開發(fā)環(huán)境服務(wù)器上,如何遠(yuǎn)程調(diào)試,本文主要介紹了idea遠(yuǎn)程Debug部署在服務(wù)器上的服務(wù),具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12
Java使用StampedLock實(shí)現(xiàn)高效讀寫功能
StampedLock 是 Java 8 引入的高性能鎖,提供了三種鎖模式:寫鎖、悲觀讀鎖和樂觀讀鎖,與傳統(tǒng)的 ReentrantReadWriteLock 相比,StampedLock 更注重性能,特別適合讀多寫少的場景,所以本文給大家介紹了Java使用StampedLock實(shí)現(xiàn)高效讀寫功能,需要的朋友可以參考下2025-01-01
java阻塞隊(duì)列實(shí)現(xiàn)原理及實(shí)例解析
這篇文章主要介紹了java阻塞隊(duì)列實(shí)現(xiàn)原理及實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
Java向上轉(zhuǎn)型和向下轉(zhuǎn)型實(shí)例解析
這篇文章主要介紹了Java向上轉(zhuǎn)型和向下轉(zhuǎn)型實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
java基于quasar實(shí)現(xiàn)協(xié)程池的方法示例
本文主要介紹了java基于quasar實(shí)現(xiàn)協(xié)程池的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧<BR>2022-06-06
簡單聊聊Java中驗(yàn)證碼功能的實(shí)現(xiàn)
相信大家都經(jīng)常接觸到驗(yàn)證碼的,畢竟平時(shí)上網(wǎng)也能遇到各種驗(yàn)證碼,需要我們輸入驗(yàn)證碼進(jìn)行驗(yàn)證我們是人類,本篇文章就從這幾個(gè)方面出發(fā)說說驗(yàn)證碼,廢話不多說,下面開始正文2023-06-06
Spring Boot利用@Async異步調(diào)用:使用Future及定義超時(shí)詳解
這篇文章主要給大家介紹了關(guān)于Spring Boot利用@Async異步調(diào)用:使用Future及定義超時(shí)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2018-05-05

