今天弄一下spring-boot和jpa的多数据源整合
Jpa(Java Persistence API)Java持久化API,它是一套ORM规范
只是一套规范
Spring Boot中使用的Jpa实际上是Spring Data Jpa,Spring Data是Spring家族的一个子项目,用于简化SQL和NoSQL的访问,在Spring Data中,只要你的方法名称符合规范,它就知道你想干嘛,不需要自己再去写SQL。
接下来我们简单来弄下,直接
在idea里创建spring-boot工程,勾选web里的web和sql里的JPA和mysql依赖
文章图片
然后在依赖里,写一下mysql的版本,一般五点几就行了,再添加Druid依赖
依赖如下
4.0.0 org.springframework.boot
spring-boot-starter-parent
2.1.5.RELEASE
com.liy
jpa
0.0.1-SNAPSHOT
jpa
Demo project for Spring Boot 1.8
org.springframework.boot
spring-boot-starter-data-jpa
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
runtime
5.1.27
com.alibaba
druid-spring-boot-starter
1.1.10
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
然后写配置信息
application.properties
spring.datasource.one.username=root
spring.datasource.one.password=root
spring.datasource.one.url=jdbc:mysql:///again
spring.datasource.one.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.two.username=root
spring.datasource.two.password=root
spring.datasource.two.url=jdbc:mysql:///demo
spring.datasource.two.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource#数据库平台
spring.jpa.properties.database-platform=mysql
#如果再次运行,检查表是否要更新
spring.jpa.properties.hibernate.ddl-auto=update
#sql信息打印
spring.jpa.properties.show-sql=true
#定义数据库的方言
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialectspring.jpa.properties.database=mysql
写个bean类。写好bean类就可以运行下工程,它会自动在数据库里生成相对应的表
package com.liy.bean;
import javax.persistence.*;
//生成数据库表的关键注解,后面的name是表名
@Entity(name = "book")
public class Book {
//必须写个id
@Id
//也必须设置为主键,以及自增长
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
//给他起别名,设置约束什么的也是@Column注解里去设置
@Column(name = "bookname")
private String username;
private String auther;
public Book() {
super();
}public Book(String username, String auther) {
this.username = username;
this.auther = auther;
}@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}@Override
protected void finalize() throws Throwable {
super.finalize();
}@Override
public String toString() {
return "Book{" +
"id=" + id +
", username='" + username + '\'' +
", auther='" + auther + '\'' +
'}';
}public int getId() {
return id;
}public void setId(int id) {
this.id = id;
}public String getUsername() {
return username;
}public void setUsername(String username) {
this.username = username;
}public String getAuther() {
return auther;
}public void setAuther(String auther) {
this.auther = auther;
}
}
【spring|spring-boot和JPA多数据源整合】然后写个区分两个数据的DataSource配置类
DataSourceConfig
@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();
}
}
然后写两个jpa的配置类,分别对应两个数据源JpaConfig@Configuration
@EnableJpaRepositories(basePackages = "com.liy.dao1",
entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanOne",
transactionManagerRef = "platformTransactionManagerOne")
public class JpaConfig {@Autowired
@Qualifier(value = "https://www.it610.com/article/dsOne")
DataSource dsOne;
@Autowired
JpaProperties jr;
@Bean
@Primary
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanOne(EntityManagerFactoryBuilder builder){
return builder.dataSource(dsOne)
.properties(jr.getProperties())
.packages("com.liy.bean")
.persistenceUnit("pu1")
.build();
}@Bean
@Primary
PlatformTransactionManager platformTransactionManagerOne(EntityManagerFactoryBuilder builder){
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = localContainerEntityManagerFactoryBeanOne(builder);
return new JpaTransactionManager(localContainerEntityManagerFactoryBean.getObject());
}
}
JpaConfig1 ,其中代码基本一样,要在一个配置类中的两个方法都加上@Primary注解 ,我都加在上面那个了
@Configuration
@EnableJpaRepositories(basePackages = "com.liy.dao2",
entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanTwo",
transactionManagerRef = "platformTransactionManagerTwo")
public class JpaConfig1 {@Autowired
@Qualifier(value = "https://www.it610.com/article/dsTwo")
DataSource dsTwo;
@Autowired
JpaProperties jr;
@Bean
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanTwo(EntityManagerFactoryBuilder builder){
return builder.dataSource(dsTwo)
.properties(jr.getProperties())
.packages("com.liy.bean")
.persistenceUnit("pu2")
.build();
}@Bean
PlatformTransactionManager platformTransactionManagerTwo(EntityManagerFactoryBuilder builder){
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = localContainerEntityManagerFactoryBeanTwo(builder);
return new JpaTransactionManager(localContainerEntityManagerFactoryBean.getObject());
}
}
然后根据上面JpaConfig的扫描负责的包来写两个dao包
![spring|spring-boot和JPA多数据源整合](https://img.it610.com/image/info8/5067cac04b834be38b9d6731c777f48f.jpg)
文章图片
BookDao1
package com.liy.dao1;
import com.liy.bean.Book;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
public interface BookDao1 extends JpaRepository {//方法名可以靠拼接,相当于自定义sql
public List findBookByIdGreaterThanAndAndUsernameContains(Integer id,String usernames);
@Query(value = "https://www.it610.com/article/select count(*) from book",nativeQuery = true)
public long TotalCount();
//如果sql语句不是查询,那么必须加@Modifying注解
//另外在对数据库进行DML(update,delete,insert)操作时,必须加上事物,也就是@Transactional
//@Transactional记得不要导错包
//import org.springframework.transaction.annotation.Transactional;
@Query(value = "https://www.it610.com/article/update book set auther=:autherwhere id=:id",nativeQuery = true)
@Modifying
@Transactional
public int update(@Param("id") int id,@Param("auther") String auther);
@Query(value = "https://www.it610.com/article/update book set bookname=:booknamewhere id=:id",nativeQuery = true)
@Modifying
public int update1(@Param("id") int id ,@Param("bookname") String bookname);
}
BookDao2
package com.liy.dao2;
import com.liy.bean.Book;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
public interface BookDao2 extends JpaRepository {@Query(value = "https://www.it610.com/article/update book set auther=:autherwhere id=:id",nativeQuery = true)
@Modifying
@Transactional
public int update1(@Param("id") int id,@Param("auther") String auther);
}
然后在spring-boot自带的测试类里进行测试
package com.liy;
import com.liy.bean.Book;
import com.liy.dao1.BookDao1;
import com.liy.dao2.BookDao2;
import com.liy.service.BookService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class JpaApplicationTests {@Autowired
BookDao1 db1;
@Autowired
BookDao2 db2;
@Test
public void updateMany(){
db1.update(3,"liy1");
db2.update1(3,"liy1");
}@Test
public void TestFind() {List a = db1.findBookByIdGreaterThanAndAndUsernameContains(1, "a");
System.out.println(a);
long l = db1.TotalCount();
System.out.println(l);
db1.update(3,"aaaa");
}@Test
public void contextLoads() {
Book book = new Book("老夫子", "afaf");
db1.save(book);
}@Test
public void update(){
Book book = new Book("老夫子", "老夫");
book.setId(1);
db1.saveAndFlush(book);
}@Test
public void find(){List all = db1.findAll(Sort.by(new Sort.Order(Sort.Direction.DESC, "id")));
System.out.println(all);
}@Test
public void findPage(){
PageRequest data = https://www.it610.com/article/PageRequest.of(0, 2);
System.out.println(data);
Page page = db1.findAll(data);
System.out.println(page.getNumberOfElements());
//当前记录数
System.out.println(page.getNumber());
//
System.out.println(page.getSize());
//每页应该查到的记录数
System.out.println(page.isLast());
//是否是最后一页
System.out.println(page.isFirst());
//是否是第一页
System.out.println(page.getTotalPages());
//总页数
System.out.println(page.getTotalElements());
//总记录数
System.out.println(page.getContent());
//当前页的数据}
}
数据库里
![spring|spring-boot和JPA多数据源整合](https://img.it610.com/image/info8/80b9861d70284caab224cb961799521b.jpg)
文章图片
在两个数据库里用两个表
第一个表是在spring-boot工程了写了个bean类,自动生成的
我为了方便,直接把上面的复制了,表结构,数据都复制,然后下面的修改下就可以了
![spring|spring-boot和JPA多数据源整合](https://img.it610.com/image/info8/2d90a66dcad1489eafff3e4ee90a6367.jpg)
文章图片
显示运行了两条sql语句,然后再看下数据库里数据是否改变即可
这个打印sql语句的在application.properties里配置 我写了注释的
推荐阅读
- java|写简洁java代码的小技巧
- Spring|SpringBoot整合Redis实现缓存(自动缓存 + 手动aop缓存)
- 服务端_java|SpringCloud极简入门>消息总线#bus
- SpringBoot|SpringBoot 札记 (SpringSecurity入门与整合)
- SpringBoot|SpringBoot 札记(入门)
- spring源码|spring源码-生命周期
- spring初始化&循环引用
- Java毕业设计项目实战篇|Java项目:(小程序)物业管理系统(spring+spring mvc+mybatis+layui+微信小程)
- =======j2ee|spring用注解实现注入的@resource,@autowired,@inject区别