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 ...
随机推荐
- Python中的字符编码
一.文本编辑器存取文件的原理: #1.打开编辑器就打开了启动了一个进程,是在内存中的,所以,用编辑器编写的内容也都是存放与内存中的,断电后数据丢失 #2.要想永久保存,需要点击保存按钮:编辑器把内存的 ...
- JcApiHelper 简单好用的.Net ApiHelper
一 背景 随着前端技术的不断发展,各种框架逐渐成熟,前端 Angular,React,Vue 三分天下.再加上移动端的崛起,前后端分离开发成为主流,前端后端代码混合开发的方式沦为被淘汰的局面.如今 M ...
- c++2的幂次方
c++2的幂次方 题目描述 任何一个正整数都可以用2的幂次方表示. 同时约定用括号来表示方次,即a的b次,可以表示为a(b). 由此可知,137可以表示为: 2(7)+2(3)+2(0) 进一步: ...
- Java连载5-标识符、关键字和字面值
一.标识符 1.标识符定义:在java源程序中凡是可以自己命名的单词 2.标识符可以标识什么元素? (1)类名(2)方法名(3)变量名(4)接口名(5)常量名 等等 3.标识符的命名要求 (1)一个合 ...
- 【POJ - 3050】Hopscotch (dfs+回溯)
-->Hopscotch 这接写中文了 Descriptions: 奶牛们以一种独特的方式玩孩子们的跳房子游戏. 奶牛们创造了一个5x5的格子 他们熟练地跳上其中的一个格子,可以前后左右地跳(不 ...
- java截取避免空字符丢失
1. 场景描述 数据后端是Hbase等nosql数据库,返回的数据以逗号分隔,java后端获取数据后,需要新增组装数据后再返回给前端. 2. 问题解决 2.1 问题定位 本来用的java的split进 ...
- java算法题每日一练01,java入门简单算法题小练
1.给数组做反序 public class Ak01 { public static void main(String[] args) { int[] a = new int[]{22,48,41,2 ...
- 微信小程序 setData 数组 渲染问题 删除之后的数组渲染不正确
list: [ { id: , mode: , src: ' }, { id: , mode: , src: ' }, { id: , mode: , src: ' } ], onDelete(e) ...
- .NET CORE 多语言实现方案
根据市场需求,基于.NET CORE平台开发的RoadFlow工作流平台需要实现多语言版本.经过方案讨论和比对,决定采用.NET自带的本地化功能来实现多语言.话不多说,直接上实现方式. 首先修改Sta ...
- GIL与异步回调
07.07自我总结 一.GIL 1.概念 在CPython中,这个全局解释器锁,也称为GIL,是一个互斥锁 2.带来的问题 首先必须明确执行一个py文件,分为三个步骤 从硬盘加载Python解释器到内 ...