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.models").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.models").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
Spring Boot 整合 JPA 使用多个数据源的更多相关文章
- Spring Boot2 系列教程(二十五)Spring Boot 整合 Jpa 多数据源
本文是 Spring Boot 整合数据持久化方案的最后一篇,主要和大伙来聊聊 Spring Boot 整合 Jpa 多数据源问题.在 Spring Boot 整合JbdcTemplate 多数据源. ...
- spring boot 系列之四:spring boot 整合JPA
上一篇我们讲了spring boot 整合JdbcTemplate来进行数据的持久化, 这篇我们来说下怎么通过spring boot 整合JPA来实现数据的持久化. 一.代码实现 修改pom,引入依赖 ...
- Spring Boot整合JPA、Redis和Swagger2
好久没有总结了,最近也一直在学习.今天就把spring boot与其它技术的整合做个小总结,主要是jpa.redis和swagger2.公司里有用到这些,整合起来也很简单. 首先,新建一个Spring ...
- Spring Boot2 系列教程(二十四)Spring Boot 整合 Jpa
Spring Boot 中的数据持久化方案前面给大伙介绍了两种了,一个是 JdbcTemplate,还有一个 MyBatis,JdbcTemplate 配置简单,使用也简单,但是功能也非常有限,MyB ...
- spring boot 整合JPA多数据源
上个文章介绍了spring boot在使用Mybatis持久化技术的时候如何使用多数据源,今天再补充一个使用spring data jpa实现多数据源的使用情况,JPA是一套数据库持久化规范,或者称之 ...
- Spring Boot 整合 Mybatis 实现 Druid 多数据源详解
摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “清醒时做事,糊涂时跑步,大怒时睡觉,独处时思考” 本文提纲一.多数据源的应用场景二.运行 sp ...
- Spring Boot从入门到精通之:二、Spring Boot整合JPA
springboot-jpa 开发工具 系统: windows10 开发工具: Intellij IDEA 2018.2.6 springboot: 2.0.6.RELEASE jdk: 1.8.0_ ...
- spring boot - 整合jpa
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring- ...
- spring boot 整合JPA bean注入失败
有时候报的错误让你匪夷所思,找错误得学会找根.源头在哪里? 比如:我们刚开始看的错误就是 org.springframework.beans.factory.UnsatisfiedDependency ...
随机推荐
- Codeforces Gym100502H:Clock Pictures(KMP算法)
http://codeforces.com/gym/100502/attachments 题意:有两个时钟上面有n个指针,给出的数字代表指针的角度.问能否在某一时刻使得两个时钟的指针重合. 思路:容易 ...
- javascript中bind绑定接收者与函数柯里化
如果我要遍历一个数组, 我只要给forEach传一个匿名函数即可,很简单: let arr = ['a', 'b', 'c']; arr.forEach((item, index) => { c ...
- Linux命令学习-mv命令
Linux中,mv命令的全称是move,主要作用是移动文件或文件夹,类似于Windows下的剪切功能,同时还可以用于修改名字. 假设当前处于wintest用户的主目录,路径为 /home/wintes ...
- c++ 二分答案
c++ 二分答案 问题 使得x^x达到或超过n位数字的最小正整数x是多少?n<=2000000000 分析 对与这种较难求解的问题,我们很难想出较好的解决策略.但是,我们至少知道答案一定在1与2 ...
- 第八章 Fisco Bcos 国密版本的部署、控制台搭建、合约的部署、sdk 调用
鉴于笔者以前各大博客教程都有很多人提问,早期建立一个技术交流群,里面技术体系可能比较杂,想了解相关区块链开发,技术提问,请加QQ群:538327407 参考资料 证书说明:https://mp.wei ...
- CDQZ集训DAY6 日记
又炸了. 早上起来其他竞赛生也走了,食堂做饭做的挺潦草,但为什么四川烧麦的馅是米啊??!! 起来看题总觉得都似曾相识.第一题打完40分暴力后想拿莫队搞到70分,但发现能想到的莫队维护都是nsqrt(n ...
- ServiceFabric极简文档-1.1 附属文件:规划和准备 Service Fabric 独立群集部署
准备好要充当节点的计算机 下面是要添加到群集的每台计算机的建议规格: 至少 16 GB RAM 至少 40 GB 可用磁盘空间 4 核或更高规格的 CPU 所有计算机与安全网络连接 Windows S ...
- OpenCV多版本切换和配置--opencv 安装与卸载、添加 opencv_contrib modules 以及 OpenCv 多版本切换
1. 查看安装Opencv的版本.以及libs和cflags $ pkg-config --modversion opencv $ pkg-config --cflags opencv // 编译链接 ...
- a=re.findall('b',c)报错提示:TypeError:expected string or buffer
目的:想通过findall选取某个unicode编码的字符串列表(列表里面有元组) 问题:报错[TypeError:expected string or buffer] 现在测试下: 定义一个有元组的 ...
- 洛谷P4994 终于结束的起点 题解
求赞,求回复,求关注~ 题目:https://www.luogu.org/problemnew/show/P4994 这道题和斐波那契数列的本质没有什么区别... 分析: 这道题应该就是一个斐波那契数 ...