1. 程式人生 > >Spring Boot2 系列教程(二十五)Spring Boot 整合 Jpa 多資料來源

Spring Boot2 系列教程(二十五)Spring Boot 整合 Jpa 多資料來源

本文是 Spring Boot 整合資料持久化方案的最後一篇,主要和大夥來聊聊 Spring Boot 整合 Jpa 多資料來源問題。在 Spring Boot 整合JbdcTemplate 多資料來源、Spring Boot 整合 MyBatis 多資料來源以及 Spring Boot 整合 Jpa 多資料來源這三個知識點中,整合 Jpa 多資料來源算是最複雜的一種,也是很多人在配置時最容易出錯的一種。本文大夥就跟著鬆哥的教程,一步一步整合 Jpa 多資料來源。

工程建立

首先是建立一個 Spring Boot 工程,建立時新增基本的 Web、Jpa 以及 MySQL 依賴,如下:

建立完成後,新增 Druid 依賴,這裡和前文的要求一樣,要使用專為 Spring Boot 打造的 Druid,大夥可能發現了,如果整合多資料來源一定要使用這個依賴,因為這個依賴中才有 DruidDataSourceBuilder,最後還要記得鎖定資料庫依賴的版本,因為可能大部分人用的還是 5.x 的 MySQL 而不是 8.x。完整依賴如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.28</version>
    <scope>runtime</scope>
</dependency>

如此之後,工程就建立成功了。

基本配置

在基本配置中,我們首先來配置多資料來源基本資訊以及 DataSource,首先在 application.properties 中新增如下配置資訊:

#  資料來源一
spring.datasource.one.username=root
spring.datasource.one.password=root
spring.datasource.one.url=jdbc:mysql:///test01?useUnicode=true&characterEncoding=UTF-8
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource

#  資料來源二
spring.datasource.two.username=root
spring.datasource.two.password=root
spring.datasource.two.url=jdbc:mysql:///test02?useUnicode=true&characterEncoding=UTF-8
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource

# Jpa配置
spring.jpa.properties.database=mysql
spring.jpa.properties.show-sql=true
spring.jpa.properties.database-platform=mysql
spring.jpa.properties.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect

這裡 Jpa 的配置和上文相比 key 中多了 properties,多資料來源的配置和前文一致,然後接下來配置兩個 DataSource,如下:

@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.one")
    @Primary
    DataSource dsOne() {
        return DruidDataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.two")
    DataSource dsTwo() {
        return DruidDataSourceBuilder.create().build();
    }
}

這裡的配置和前文的多資料來源配置基本一致,但是注意多了一個在 Spring 中使用較少的註解 @Primary,這個註解一定不能少,否則在專案啟動時會出錯,@Primary 表示當某一個類存在多個例項時,優先使用哪個例項。

好了,這樣,DataSource 就有了。

多資料來源配置

接下來配置 Jpa 的基本資訊,這裡兩個資料來源,我分別在兩個類中來配置,先來看第一個配置:

@Configuration
@EnableJpaRepositories(basePackages = "org.javaboy.jpa.dao",entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanOne",transactionManagerRef = "platformTransactionManagerOne")
public class JpaConfigOne {
    @Autowired
    @Qualifier(value = "dsOne")
    DataSource dsOne;
    @Autowired
    JpaProperties jpaProperties;
    @Bean
    @Primary
    LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanOne(EntityManagerFactoryBuilder builder) {
        return builder.dataSource(dsOne)
                .packages("org.javaboy.jpa.model")
                .properties(jpaProperties.getProperties())
                .persistenceUnit("pu1")
                .build();
    }
    @Bean
    PlatformTransactionManager platformTransactionManagerOne(EntityManagerFactoryBuilder builder) {
        LocalContainerEntityManagerFactoryBean factoryBeanOne = localContainerEntityManagerFactoryBeanOne(builder);
        return new JpaTransactionManager(factoryBeanOne.getObject());
    }
}

首先這裡注入 dsOne,再注入 JpaProperties,JpaProperties 是系統提供的一個例項,裡邊的資料就是我們在 application.properties 中配置的 jpa 相關的配置。然後我們提供兩個 Bean,分別是 LocalContainerEntityManagerFactoryBean 和 PlatformTransactionManager 事務管理器,不同於 MyBatis 和 JdbcTemplate,在 Jpa 中,事務一定要配置。在提供 LocalContainerEntityManagerFactoryBean 的時候,需要指定 packages,這裡的 packages 指定的包就是這個資料來源對應的實體類所在的位置,另外在這裡配置類上通過 @EnableJpaRepositories 註解指定 dao 所在的位置,以及 LocalContainerEntityManagerFactoryBean 和 PlatformTransactionManager 分別對應的引用的名字。

好了,這樣第一個就配置好了,第二個基本和這個類似,主要有幾個不同點:

  • dao 的位置不同
  • persistenceUnit 不同
  • 相關 bean 的名稱不同

注意實體類可以共用。

程式碼如下:

@Configuration
@EnableJpaRepositories(basePackages = "org.javaboy.jpa.dao2",entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanTwo",transactionManagerRef = "platformTransactionManagerTwo")
public class JpaConfigTwo {
    @Autowired
    @Qualifier(value = "dsTwo")
    DataSource dsTwo;
    @Autowired
    JpaProperties jpaProperties;
    @Bean
    LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanTwo(EntityManagerFactoryBuilder builder) {
        return builder.dataSource(dsTwo)
                .packages("org.javaboy.jpa.model")
                .properties(jpaProperties.getProperties())
                .persistenceUnit("pu2")
                .build();
    }
    @Bean
    PlatformTransactionManager platformTransactionManagerTwo(EntityManagerFactoryBuilder builder) {
        LocalContainerEntityManagerFactoryBean factoryBeanTwo = localContainerEntityManagerFactoryBeanTwo(builder);
        return new JpaTransactionManager(factoryBeanTwo.getObject());
    }
}

接下來,在對應位置分別提供相關的實體類和 dao 即可,資料來源一的 dao 如下:

package org.javaboy.jpa.dao;
public interface UserDao extends JpaRepository<User,Integer> {
    List<User> getUserByAddressEqualsAndIdLessThanEqual(String address, Integer id);
    @Query(value = "select * from t_user where id=(select max(id) from t_user)",nativeQuery = true)
    User maxIdUser();
}

資料來源二的 dao 如下:

package org.javaboy.jpa.dao2;
public interface UserDao2 extends JpaRepository<User,Integer> {
    List<User> getUserByAddressEqualsAndIdLessThanEqual(String address, Integer id);

    @Query(value = "select * from t_user where id=(select max(id) from t_user)",nativeQuery = true)
    User maxIdUser();
}

共同的實體類如下:

package org.javaboy.jpa.model;
@Entity(name = "t_user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String username;
    private String address;
    //省略getter/setter
}

到此,所有的配置就算完成了,接下來就可以在 Service 中注入不同的 UserDao,不同的 UserDao 操作不同的資料來源。

其實整合 Jpa 多資料來源也不算難,就是有幾個細節問題,這些細節問題解決,其實前面介紹的其他多資料來源整個都差不多。

好了,本文就先介紹到這裡。

相關案例已經上傳到 GitHub,歡迎小夥伴們們下載:https://github.com/lenve/javaboy-code-samples

掃碼關注鬆哥,公眾號後臺回覆 2TB,獲取鬆哥獨家 超2TB 免費 Java 學習乾貨

相關推薦

Spring Boot2 系列教程()Spring Boot 整合 Jpa 資料來源

本文是 Spring Boot 整合資料持久化方案的最後一篇,主要和大夥來聊聊 Spring Boot 整合 Jpa 多資料來源問題。在 Spring Boot 整合JbdcTemplate 多資料來源、Spring Boot 整合 MyBatis 多資料來源以及 Spring Boot 整合 Jpa 多資料

Spring Boot2 系列教程(四)Spring Boot 整合 Jpa

Spring Boot 中的資料持久化方案前面給大夥介紹了兩種了,一個是 JdbcTemplate,還有一個 MyBatis,JdbcTemplate 配置簡單,使用也簡單,但是功能也非常有限,MyBatis 則比較靈活,功能也很強大,據我所知,公司採用 MyBatis 做資料持久化的相當多,但是 MyBat

Spring Boot2 系列教程(六)Spring Boot 整合 Redis

在 Redis 出現之前,我們的快取框架各種各樣,有了 Redis ,快取方案基本上都統一了,關於 Redis,鬆哥之前有一個系列教程,尚不瞭解 Redis 的小夥伴可以參考這個教程: Redis 教程合集 使用 Java 操作 Redis 的方案很多,Jedis 是目前較為流行的一種方案,除了 Jedi

Spring Boot2 系列教程(八)Spring Boot 整合 Session 共享

這篇文章是鬆哥的原創,但是在第一次釋出的時候,忘了標記原創,結果被好多號轉發,導致我後來整理的時候自己沒法標記原創了。寫了幾百篇原創技術乾貨了,有一兩篇忘記標記原創進而造成的一點點小小損失也能接受,不過還是要和小夥伴們說明一下。 在傳統的單服務架構中,一般來說,只有一個伺服器,那麼不存在 Session

Spring Boot2 系列教程(九)Spring Boot 整合 Redis

經過 Spring Boot 的整合封裝與自動化配置,在 Spring Boot 中整合Redis 已經變得非常容易了,開發者只需要引入 Spring Data Redis 依賴,然後簡單配下 redis 的基本資訊,系統就會提供一個 RedisTemplate 供開發者使用,但是今天鬆哥想和大夥聊的不是這種

Spring Boot2 系列教程(一)整合 MyBatis

前面兩篇文章和讀者聊了 Spring Boot 中最簡單的資料持久化方案 JdbcTemplate,JdbcTemplate 雖然簡單,但是用的並不多,因為它沒有 MyBatis 方便,在 Spring+SpringMVC 中整合 MyBatis 步驟還是有點複雜的,要配置多個 Bean,Spring Boo

Spring Boot2 系列教程(十三)理解 Spring Data Jpa

有很多讀者留言希望鬆哥能好好聊聊 Spring Data Jpa! 其實這個話題鬆哥以前零零散散的介紹過,在我的書裡也有介紹過,但是在公眾號中還沒和大夥聊過,因此本文就和大家來仔細聊聊 Spring Data 和 Jpa! 本文大綱: 1. 故事的主角 1.1 Jpa 1.1.1 JPA 是什麼 Jav

Spring Boot2 系列教程(三一)Spring Boot 構建 RESTful 風格應用

RESTful ,到現在相信已經沒人不知道這個東西了吧!關於 RESTful 的概念,我這裡就不做過多介紹了,傳統的 Struts 對 RESTful 支援不夠友好 ,但是 SpringMVC 對於 RESTful 提供了很好的支援,常見的相關注解有: @RestController @GetMapping

Spring Boot2 系列教程()建立 Spring Boot 專案的三種方式

我最早是 2016 年底開始寫 Spring Boot 相關的部落格,當時使用的版本還是 1.4.x ,文章發表在 CSDN 上,閱讀量最大的一篇有 43W+,如下圖: 2017 年由於種種原因,就沒有再繼續更新 Spring Boot 相關的部落格了,2018年又去寫書了,也沒更新,現在 Spring

Spring Boot2 系列教程(三)Spring Boot 整合 Ehcache

用慣了 Redis ,很多人已經忘記了還有另一個快取方案 Ehcache ,是的,在 Redis 一統江湖的時代,Ehcache 漸漸有點沒落了,不過,我們還是有必要了解下 Ehcache ,在有的場景下,我們還是會用到 Ehcache。 今天鬆哥就來和大家聊聊 Spring Boot 中使用 Ehcach

Spring Boot2 系列教程(六)自定義 Spring Boot 中的 starter

我們使用 Spring Boot,基本上都是沉醉在它 Stater 的方便之中。Starter 為我們帶來了眾多的自動化配置,有了這些自動化配置,我們可以不費吹灰之力就能搭建一個生產級開發環境,有的小夥伴會覺得這個 Starter 好神奇呀!其實 Starter 也都是 Spring + SpringMVC

Spring cloud系列教程篇- Spring cloud整合Eureka總結篇

Spring cloud系列教程第十篇- Spring cloud整合Eureka總結篇 本文主要內容: 1:spring cloud整合Eureka總結 本文是由凱哥(凱哥Java:kagejava)釋出的《spring cloud系列》教程的總第十篇: 本文是幾個維度中的第一個維度:註冊與發現維度配置中心

Spring Boot2 系列教程()@ControllerAdvice 的三種使用場景

嚴格來說,本文並不算是 Spring Boot 中的知識點,但是很多學過 SpringMVC 的小夥伴,對於 @ControllerAdvice 卻並不熟悉,Spring Boot 和 SpringMVC 一脈相承,@ControllerAdvice 在 Spring Boot 中也有廣泛的使用場景,因此本文

Spring Boot2 系列教程()定義系統啟動任務的兩種方式

在 Servlet/Jsp 專案中,如果涉及到系統任務,例如在專案啟動階段要做一些資料初始化操作,這些操作有一個共同的特點,只在專案啟動時進行,以後都不再執行,這裡,容易想到web基礎中的三大元件( Servlet、Filter、Listener )之一 Listener ,這種情況下,一般定義一個 Serv

Spring Boot2 系列教程()Spring Boot中的 yaml 配置

搞 Spring Boot 的小夥伴都知道,Spring Boot 中的配置檔案有兩種格式,properties 或者 yaml,一般情況下,兩者可以隨意使用,選擇自己順手的就行了,那麼這兩者完全一樣嗎?肯定不是啦!本文就來和大夥重點介紹下 yaml 配置,最後再來看看 yaml 和 properties 配

Spring Boot2 系列教程()Spring Boot 整合 Freemarker

今天來聊聊 Spring Boot 整合 Freemarker。 Freemarker 簡介 這是一個相當老牌的開源的免費的模版引擎。通過 Freemarker 模版,我們可以將資料渲染成 HTML 網頁、電子郵件、配置檔案以及原始碼等。Freemarker 不是面向終端使用者的,而是一個 Java 類庫,我

Spring Boot2 系列教程(一)Spring Boot 中的靜態資源配置

當我們使用 SpringMVC 框架時,靜態資源會被攔截,需要新增額外配置,之前老有小夥伴在微信上問鬆哥 Spring Boot 中的靜態資源載入問題:“鬆哥,我的 HTML 頁面好像沒有樣式?”,今天我就通過一篇文章,來和大夥仔細聊一聊這個問題。 1. SSM 中的配置 要講 Spring Boot 中的問

Spring Boot2 系列教程(四)CORS 解決跨域問題

今天和小夥伴們來聊一聊通過CORS解決跨域問題。 同源策略 很多人對跨域有一種誤解,以為這是前端的事,和後端沒關係,其實不是這樣的,說到跨域,就不得不說說瀏覽器的同源策略。 同源策略是由 Netscape 提出的一個著名的安全策略,它是瀏覽器最核心也最基本的安全功能,現在所有支援 JavaScript 的瀏覽

Spring Boot2 系列教程(六)定時任務的兩種實現方式

在 Spring + SpringMVC 環境中,一般來說,要實現定時任務,我們有兩中方案,一種是使用 Spring 自帶的定時任務處理器 @Scheduled 註解,另一種就是使用第三方框架 Quartz ,Spring Boot 源自 Spring+SpringMVC ,因此天然具備這兩個 Spring

Spring Boot2 系列教程(七)SpringBoot 整合 Swagger2

前後端分離後,維護介面文件基本上是必不可少的工作。 一個理想的狀態是設計好後,介面文件發給前端和後端,大夥按照既定的規則各自開發,開發好了對接上了就可以上線了。當然這是一種非常理想的狀態,實際開發中卻很少遇到這樣的情況,介面總是在不斷的變化之中,有變化就要去維護,做過的小夥伴都知道這件事有多麼頭大!還好,有一