Spring Boot 整合 JPA 使用多個數據源


介紹

JPA(Java Persistence API)Java 持久化 API,是 Java 持久化的標准規范,Hibernate 是持久化規范的技術實現,而 Spring Data JPA 是在 Hibernate 基礎上封裝的一款框架。
第一次使用 Spring JPA 的時候,感覺這東西簡直就是神器,幾乎不需要寫什么關於數據庫訪問的代碼一個基本的 CURD 的功能就出來了。在這篇文章中,我們將介紹 Spring Boot 整合 JPA 使用多個數據源的方法。
開發環境:

  • Spring Boot 2.0.5
  • Spring Data JPA 2.0.5
  • MySQL 5.6
  • JDK 8
  • IDEA 2018.3
  • Windows 10

引入依賴

首先我們要 Spring Boot 引入 spring-boot-starter-data-jpa 依賴。

Maven 配置:

   <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>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>

Gradle 配置:

compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.0.5.RELEASE' compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.5.RELEASE' compile group: 'org.springframework.boot', name: 'spring-boot-devtools', version: '2.0.5.RELEASE' compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.6'

配置數據源

Spring Boot 提供了使用 application.properties 或 application.yml 文件配置項目屬性的方法。我比較習慣使用 application.yml 文件,所以這里我只列出 application.yml 文件的寫法。

spring:
  datasource:
    product:
      driver-class-name: com.mysql.jdbc.Driver
      jdbc-url: jdbc:mysql://127.0.0.1:3306/product?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull username: root password: test123$ customer: driver-class-name: com.mysql.jdbc.Driver jdbc-url: jdbc:mysql://127.0.0.1:3306/customer?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull username: root password: test123$ jpa: generate-ddl: true

配置好 application.yml 文件后分別在數據庫創建 customer 和 product 數據庫。

添加實體(Entity)類

客戶實體:

package com.springboot.jpa.customer.models; import javax.persistence.*; @Entity public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(unique = true, nullable = false) private String email; private String firstName; private String lastName; protected Customer() { } public Customer(String email, String firstName, String lastName) { this.email = email; this.firstName = firstName; this.lastName = lastName; } @Override public String toString() { return String.format("Customer[id=%d, firstName='%s', lastName='%s',email='%s']", id, firstName, lastName, email); } public Integer getId() { return id; } public String getEmail() { return email; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } }

產品實體:

package com.springboot.jpa.product.models; import javax.persistence.*; @Entity public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column(nullable = false) private String code; private String name; private double price; protected Product() { } public Product(String code, String name, double price) { this.code = code; this.name = name; this.price = price; } @Override public String toString() { return String.format("Product[id=%d, code='%s', name='%s', price='%s']", id, code, name, price); } public int getId() { return id; } public String getCode() { return code; } public String getName() { return name; } public double getPrice() { return price; } } 

添加數據倉庫(Repository)類

客戶 Repository:

package com.springboot.jpa.customer.repository; import com.springboot.jpa.customer.models.Customer; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface CustomerRepository extends JpaRepository<Customer, Integer> { }

產品 Repository:

package com.springboot.jpa.product.repository; import com.springboot.jpa.product.models.Product; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface ProductRepository extends JpaRepository<Product, Integer> { }

添加配置(Config)類

客戶配置:

package com.springboot.jpa.customer.config; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; 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.persistence.EntityManagerFactory; import javax.sql.DataSource; @Configuration @EnableTransactionManagement @EnableJpaRepositories(entityManagerFactoryRef = "customerEntityManagerFactory", transactionManagerRef = "customerTransactionManager", basePackages = {"com.springboot.jpa.customer.repository"}) public class CustomerConfig { @Primary @Bean(name = "customerDataSource") @ConfigurationProperties(prefix = "spring.datasource.customer") public DataSource customerDataSource() { return DataSourceBuilder.create().build(); } @Primary @Bean(name = "customerEntityManagerFactory") public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("customerDataSource") DataSource dataSource) { return builder.dataSource(dataSource).packages("com.springboot.jpa.customer.data").persistenceUnit("customer").build(); } @Primary @Bean(name = "customerTransactionManager") public PlatformTransactionManager customerTransactionManager(@Qualifier("customerEntityManagerFactory") EntityManagerFactory customerEntityManagerFactory) { return new JpaTransactionManager(customerEntityManagerFactory); } }

產品配置:

package com.springboot.jpa.product.config; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; 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.persistence.EntityManagerFactory; import javax.sql.DataSource; @Configuration @EnableTransactionManagement @EnableJpaRepositories(entityManagerFactoryRef = "productEntityManagerFactory", transactionManagerRef = "productTransactionManager", basePackages = {"com.springboot.jpa.product.repository"} ) public class ProductConfig { @Bean(name = "productDataSource") @ConfigurationProperties(prefix = "spring.datasource.product") public DataSource dataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "productEntityManagerFactory") public LocalContainerEntityManagerFactoryBean barEntityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("productDataSource") DataSource dataSource) { return builder.dataSource(dataSource).packages("com.springboot.jpa.product.data").persistenceUnit("product").build(); } @Bean(name = "productTransactionManager") public PlatformTransactionManager productTransactionManager(@Qualifier("productEntityManagerFactory") EntityManagerFactory productEntityManagerFactory) { return new JpaTransactionManager(productEntityManagerFactory); } }

項目結構:

src/main/java
- com.springboot.jpa
      - product
        - config
        - models
        - repository
      - customer
        - config
        - models
        - repository

添加測試類

客戶測試類 CustomerDataSourcesTests:

package com.springboot.jpa; import com.springboot.jpa.customer.repository.CustomerRepository; import com.springboot.jpa.customer.models.Customer; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @RunWith(SpringRunner.class) @SpringBootTest public class CustomerDataSourcesTests { @Autowired private CustomerRepository customerRepository; @Test @Transactional("customerTransactionManager") public void createCustomer() { Customer customer = new Customer("master@weilog.net", "Charles", "Zhang"); customer = customerRepository.save(customer); assertNotNull(customerRepository.findById(customer.getId())); assertEquals(customerRepository.findById(customer.getId()).get().getEmail(), "master@weilog.net"); } }

產品測試類 ProductDataSourcesTests:

package com.springboot.jpa; import com.springboot.jpa.product.models.Product; import com.springboot.jpa.product.repository.ProductRepository; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import org.junit.Test; import static org.junit.Assert.assertNotNull; @RunWith(SpringRunner.class) @SpringBootTest public class ProductDataSourcesTests { @Autowired private ProductRepository productRepository; @Test @Transactional("productTransactionManager") public void createProduct() { Product product = new Product("10000", "Book", 80.0); product = productRepository.save(product); assertNotNull(productRepository.findById(product.getId())); } }

測試

分別運行兩個測試類通過后,查詢數據庫。
客戶表:

mysql> SELECT * FROM customer;
+----+-------------------+-----------+----------+
| id | email             | firstName | lastName |
+----+-------------------+-----------+----------+
|  1 | master@weilog.net | Charles   | Zhang    |
+----+-------------------+-----------+----------+
1 row in set

產品表:

mysql> SELECT * FROM product;
+----+-------+------+-------+
| id | code  | name | price |
+----+-------+------+-------+
|  1 | 10000 | Book |    80 |
+----+-------+------+-------+
1 row in set

本文地址:Spring Boot 整合 JPA 使用多個數據源
項目地址:spring-boot-jpa

作者:Charles Zhang


出處:https://www.cnblogs.com/weisenz/


本站使用「署名 4.0 國際」創作共享協議,轉載請在文章明顯位置注明作者及出處。

 
分類 Java , Spring Boot


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM