SpringBoot整合JPA
1、Spring Data JPA概述
SpringData
:Spring 的一个子项目。用于简化数据库访问,支持NoSQL 和 关系数据存储。其主要目标是使数据
库的访问变得方便快捷。
JPA
:JPA(Java Persistence API,Java持久化API),定义了对象关系映射(Object Relation Mapping,ORM)以及实
体对象持久化的标准接口。Hibernate实现了JPA的一个ORM框架。
JPA Spring Data
:致力于减少数据访问层 (DAO) 的开发量,开发者唯一要做的,就只是声明持久层的接口,
其他都交给 Spring Data JPA 来完成。Spring Data JPA 是Spring基于ORM框架、JPA规范的基础上封装的一套JPA
应用框架。
2、SpringBoot整合JPA
2.1 建库建表
DROP TABLE IF EXISTS student ;
CREATE TABLE student (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(100) DEFAULT NULL,
sex varchar(100) DEFAULT NULL,
age int(11) DEFAULT NULL,
PRIMARY KEY ( id )
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
2.2 新建项目
目录结构如下:
2.3 添加相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/>
</parent>
<groupId>com.jpa.mysql</groupId>
<artifactId>spring-data-jpa-mysql</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-data-jpa-mysql</name>
<description>spring-data-jpa-mysql</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- jpa 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- lombok 依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.4 修改application.properties配置文件
server.port=9000
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.show-sql=true
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
2.5 编写entity
package com.jpa.mysql.entity;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
@Data
@Entity
@Table(name = "student")
public class Student implements Serializable {
@Id
@Column(name="id")
private int id;
@Column(name="name")
private String name;
@Column(name="sex")
private String sex;
@Column(name="age")
private int age;
}
2.6 编写dao
package com.jpa.gbase.dao;
import com.jpa.gbase.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface StudentDao extends JpaRepository<Student, Integer> {
List<Student> findByName(String name);
}
2.6 编写service接口
package com.jpa.gbase.service;
import com.jpa.gbase.entity.Student;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public interface IStudentService {
Student findById(Integer id);
List<Student> findAll();
List<Student> findByName(String name);
Student save(String name) throws Exception;
void delete(Integer id) throws Exception;
}
2.7 编写service实现类
package com.jpa.gbase.service.impl;
import com.jpa.gbase.dao.StudentDao;
import com.jpa.gbase.entity.Student;
import com.jpa.gbase.service.IStudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Component
public class StudentServiceImpl implements IStudentService {
@Autowired
private StudentDao studentDao;
@Override
public Student findById(Integer id) {
return studentDao.findById(id).get();
}
@Override
public List<Student> findAll() {
return studentDao.findAll();
}
@Override
public List<Student> findByName(String name) {
return studentDao.findByName(name);
}
@Override
@Transactional
public Student save(String name) throws Exception {
Student student = new Student();
student.setName(name);
student.setSex("M");
student.setAge(18);
return studentDao.save(student);
}
@Override
@Transactional
public void delete(Integer id) throws Exception {
studentDao.deleteById(id);
}
}
2.8 编写controller
package com.jpa.gbase.controller;
import com.jpa.gbase.entity.Student;
import com.jpa.gbase.service.IStudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping(value = "/student")
public class StudentController {
@Autowired
private IStudentService studentService;
@GetMapping(value = "/findById/{id}")
public Student findById(@PathVariable("id") Integer id) {
return studentService.findById(id);
}
@GetMapping(value = "/findAll")
public List<Student> findAll() {
return studentService.findAll();
}
@GetMapping(value = "/findByName/{name}")
public List<Student> findByName(@PathVariable("name") String name) {
return studentService.findByName(name);
}
@GetMapping(value = "/save/{name}")
public Student save(@PathVariable("name") String name) {
Student student = new Student();
try {
student = studentService.save(name);
} catch (Exception e) {
e.printStackTrace();
}
return student;
}
@GetMapping(value = "/delete/{id}")
public boolean delete(@PathVariable("id") Integer id) {
boolean flg = false;
try {
studentService.delete(id);
flg = true;
} catch (Exception e) {
e.printStackTrace();
}
return flg;
}
}
2.9 编写启动类
package com.jpa.mysql;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringDataJpaMysqlApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDataJpaMysqlApplication.class, args);
}
}
3.测试
3.1 添加数据
http://localhost:9000/student/save/tom
3.2 根据id查询数据
http://localhost:9000/student/findById/1
3.3 根据名字查询数据
http://localhost:9000/student/findByName/tom
3.4 根据id删除数据
http://localhost:9000/student/delete/1
3.5 查询全部数据
http://localhost:9000/student/save/tom1
http://localhost:9000/student/save/tom2
http://localhost:9000/student/save/tom3
http://localhost:9000/student/save/tom4
http://localhost:9000/student/save/tom5
http://localhost:9000/student/findAll
4、简单查询
基本查询也分为两种,一种是 Spring Data 默认已经实现,一种是根据查询的方法来自动解析成 SQL。
4.1 预先生成方法
Spring Boot Jpa 默认预先生成了一些基本的CURD的方法,例如:增、删、改等等
1、继承 JpaRepository
@Repository
public interface StudentDao extends JpaRepository<Student, Integer> {
}
2、使用默认方法
@Autowired
private StudentDao studentDao;
studentDao.findAll();
studentDao.findOne(1l);
studentDao.save(user);
studentDao.delete(user);
studentDao.count();
studentDao.exists(1l);
4.2 自定义简单查询
自定义的简单查询就是根据方法名来自动生成 SQL。
主要的语法是 findByXX
,readAByXX
,queryByXX
,countByXX
, getByXX
,XX
代表属性名称。
Student findByName(String name);
也使用一些加一些关键字And
、 Or
:
User findByNameOrSex(String username, int sex);
修改、删除、统计也是类似语法:
Long deleteById(Long id);
Long countByName(String mame);
基本上 SQL 体系中的关键词都可以使用,例如:LIKE
、 IgnoreCase
、 OrderBy
。
List<Student> findByNameLike(String name);
Student findByNameIgnoreCase(String name);
List<Student> findByNameOrderByAgeDesc(String name);
具体的关键字,使用方法和生产成SQL如下表所示:
Keyword | Sample | JPQL snippet |
---|---|---|
And |
findByLastnameAndFirstname |
… where x.lastname = ?1 and x.firstname = ?2 |
Or |
findByLastnameOrFirstname |
… where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals |
findByFirstnameIs,findByFirstnameEquals |
… where x.firstname = ?1 |
Between |
findByStartDateBetween |
… where x.startDate between ?1 and ?2 |
LessThan |
findByAgeLessThan |
… where x.age < ?1 |
LessThanEqual |
findByAgeLessThanEqual |
… where x.age <= ?1 |
GreaterThan |
findByAgeGreaterThan |
… where x.age > ?1 |
GreaterThanEqual |
findByAgeGreaterThanEqual |
… where x.age >= ?1 |
After |
findByStartDateAfter |
… where x.startDate > ?1 |
Before |
findByStartDateBefore |
… where x.startDate < ?1 |
IsNull |
findByAgeIsNull |
… where x.age is null |
IsNotNull,NotNull |
findByAge(Is)NotNull |
… where x.age not null |
Like |
findByFirstnameLike |
… where x.firstname like ?1 |
NotLike |
findByFirstnameNotLike |
… where x.firstname not like ?1 |
StartingWith |
findByFirstnameStartingWith |
… where x.firstname like ?1 (parameter bound with appended %) |
EndingWith |
findByFirstnameEndingWith |
… where x.firstname like ?1 (parameter bound with prepended %) |
Containing |
findByFirstnameContaining |
… where x.firstname like ?1 (parameter bound wrapped in %) |
OrderBy |
findByAgeOrderByLastnameDesc |
… where x.age = ?1 order by x.lastname desc |
Not |
findByLastnameNot |
… where x.lastname <> ?1 |
In |
findByAgeIn(Collection ages) |
… where x.age in ?1 |
NotIn |
findByAgeNotIn(Collection age) |
… where x.age not in ?1 |
TRUE |
findByActiveTrue() |
… where x.active = true |
FALSE |
findByActiveFalse() |
… where x.active = false |
IgnoreCase |
findByFirstnameIgnoreCase |
… where UPPER(x.firstame) = UPPER(?1) |
5、复杂查询
在实际的开发中我们需要用到分页、删选、连表等查询的时候就需要特殊的方法或者自定义 SQL。
5.1 分页查询
分页查询在实际使用中非常普遍了,Spring Boot Jpa 已经帮我们实现了分页的功能,在查询的方法中,需要传入
参数Pageable
,当查询中有多个参数的时候Pageable
建议做为最后一个参数传入。
Page<Student> findALL(Pageable pageable);
Page<Student> findByName(String name,Pageable pageable);
Pageable
是 Spring 封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则。
@Test
public void testPageQuery() throws Exception {
int page=1,size=10;
Sort sort = new Sort(Direction.DESC, "id");
Pageable pageable = new PageRequest(page, size, sort);
studentDao.findALL(pageable);
studentDao.findByName("tom", pageable);
}
5.2 限制查询
有时候我们只需要查询前N个元素,或者只取前一个实体。
Student findFirstByOrderByNameAsc();
Student findTopByOrderByAgeDesc();
Page<Student> queryFirst10ByName(String name, Pageable pageable);
List<Student> findFirst10ByName(String name, Sort sort);
List<Student> findTop10ByName(String name, Pageable pageable);
5.3 自定义SQL查询
其实 Spring Data 觉大部分的 SQL 都可以根据方法名定义的方式来实现,但是由于某些原因我们想使用自定义的
SQL 来查询,Spring Data 也是完美支持的;在 SQL 的查询方法上面使用@Query
注解,如涉及到删除和修改再需
要加上@Modifying
,也可以根据需要添加 @Transactional
对事物的支持,查询超时的设置等。
@Modifying
@Query("update student stu set stu.name = ?1 where stu.id = ?2")
int modifyNameById(String name, Long id);
@Transactional
@Modifying
@Query("delete from student where id = ?1")
void deleteById(Long id);
@Transactional(timeout = 10)
@Query("select stu from student stu where stu.id = ?1")
User findById(Long id);
5.4 多表查询
多表查询 Spring Boot Jpa 中有两种实现方式,第一种是利用 Hibernate 的级联查询来实现,第二种是创建一个结
果集的接口来接收连表查询后的结果,这里主要第二种方式。
首先需要定义一个结果集的接口类:
public interface HotelSummary {
City getCity();
String getName();
Double getAverageRating();
default Integer getAverageRatingRounded() {
return getAverageRating() == null ? null : (int) Math.round(getAverageRating());
}
}
查询的方法返回类型设置为新创建的接口:
@Query("select h.city as city, h.name as name, avg(r.rating) as averageRating "
- "from Hotel h left outer join h.reviews r where h.city = ?1 group by h")
Page<HotelSummary> findByCity(City city, Pageable pageable);
@Query("select h.name as name, avg(r.rating) as averageRating "
- "from Hotel h left outer join h.reviews r group by h")
Page<HotelSummary> findByCity(Pageable pageable);
使用:
Page<HotelSummary> hotels = this.hotelRepository.findByCity(new PageRequest(0, 10, Direction.ASC, "name"));
for(HotelSummary summay:hotels){
System.out.println("Name" +summay.getName());
}
在运行中 Spring 会给接口(HotelSummary)自动生产一个代理类来接收返回的结果,代码汇总使用 getXX
的形式来获取。
6、使用枚举
使用枚举的时候,我们希望数据库中存储的是枚举对应的 String 类型,而不是枚举的索引值,需要在属性上面添
加@Enumerated(EnumType.STRING)
注解
@Enumerated(EnumType.STRING)
@Column(nullable = true)
private UserType type;
7、不需要和数据库映射的属性
正常情况下我们在实体类上加入注解@Entity
,就会让实体类和表相关连如果其中某个属性我们不需要和数据库
来关联只是在展示的时候做计算,只需要加上@Transient
属性既可。
@Transient
private String userName;
8、多数据源的支持
8.1 同源数据库的多源支持
日常项目中因为使用的分布式开发模式,不同的服务有不同的数据源,常常需要在一个项目中使用多个数据源,因
此需要配置 Spring Boot Jpa 对多数据源的使用,一般分一下为三步:
-
1 配置多数据源
-
2 不同源的实体类放入不同包路径
-
3 声明不同的包路径下使用不同的数据源、事务支持
8.2 异构数据库多源支持
比如我们的项目中,即需要对 mysql 的支持,也需要对 Mongodb 的查询等。
实体类声明@Entity
关系型数据库支持类型,声明@Document
为 Mongodb 支持类型,不同的数据源使用不同的
实体就可以了。
interface PersonRepository extends Repository<Person, Long> {
…
}
@Entity
public class Person {
…
}
interface UserRepository extends Repository<User, Long> {
…
}
@Document
public class User {
…
}
但是,如果 User 用户既使用 Mysql 也使用 Mongodb 呢,也可以做混合使用。
interface JpaPersonRepository extends Repository<Person, Long> {
…
}
interface MongoDBPersonRepository extends Repository<Person, Long> {
…
}
@Entity
@Document
public class Person {
…
}
也可以通过对不同的包路径进行声明,比如 A 包路径下使用 mysql,B 包路径下使用 MongoDB。
@EnableJpaRepositories(basePackages = "com.neo.repositories.jpa")
@EnableMongoRepositories(basePackages = "com.neo.repositories.mongo")
interface Configuration { }
9、多数据源使用案例
9.1 导入pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>spring-boot-multi-jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-multi-jpa</name>
<description>spring-boot-multi-Jpa</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- lombok 依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
9.2 配置文件
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.primary.username=root
spring.datasource.primary.password=root
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.secondary.username=root
spring.datasource.secondary.password=root
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.hbm2ddl.auto=create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.properties.hibernate.format_sql=true
9.3 实体类
package com.example.springbootmultijpa.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.io.Serializable;
@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(nullable = false, unique = true)
private String userName;
@Column(nullable = false)
private String passWord;
@Column(nullable = false, unique = true)
private String email;
@Column(nullable = true, unique = true)
private String nickName;
@Column(nullable = false)
private String regTime;
public User(String userName, String passWord, String email, String nickName, String regTime) {
this.userName = userName;
this.passWord = passWord;
this.email = email;
this.nickName = nickName;
this.regTime = regTime;
}
}
9.4 config
package com.example.springbootmultijpa.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
public class DataSourceConfig {
@Autowired
private JpaProperties jpaProperties;
@Autowired
private HibernateProperties hibernateProperties;
@Bean(name = "primaryDataSource")
@Primary
@ConfigurationProperties("spring.datasource.primary")
public DataSource firstDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties("spring.datasource.secondary")
public DataSource secondDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "vendorProperties")
public Map<String, Object> getVendorProperties() {
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(),
new HibernateSettings());
}
}
package com.example.springbootmultijpa.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.EntityManager;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactoryPrimary",
transactionManagerRef = "transactionManagerPrimary",
basePackages = {"com.example.springbootmultijpa.repository.test1"})//设置dao(repo)所在位置
public class PrimaryConfig {
@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@Autowired
@Qualifier("vendorProperties")
private Map<String, Object> vendorProperties;
@Bean(name = "entityManagerFactoryPrimary")
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(primaryDataSource)
.properties(vendorProperties)
.packages("com.example.springbootmultijpa.model") //设置实体类所在位置
.persistenceUnit("primaryPersistenceUnit")
.build();
}
@Bean(name = "entityManagerPrimary")
@Primary
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
}
@Bean(name = "transactionManagerPrimary")
@Primary
PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
}
package com.example.springbootmultijpa.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.EntityManager;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactorySecondary",
transactionManagerRef = "transactionManagerSecondary",
basePackages = {"com.example.springbootmultijpa.repository.test2"})
public class SecondaryConfig {
@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondaryDataSource;
@Autowired
@Qualifier("vendorProperties")
private Map<String, Object> vendorProperties;
@Bean(name = "entityManagerFactorySecondary")
public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(secondaryDataSource)
.properties(vendorProperties)
.packages("com.example.springbootmultijpa.model")
.persistenceUnit("secondaryPersistenceUnit")
.build();
}
@Bean(name = "entityManagerSecondary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactorySecondary(builder).getObject().createEntityManager();
}
@Bean(name = "transactionManagerSecondary")
PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
}
}
9.5 Repository
package com.example.springbootmultijpa.repository.test1;
import com.example.springbootmultijpa.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserTest1Repository extends JpaRepository<User, Long> {
User findById(long id);
User findByUserName(String userName);
User findByUserNameOrEmail(String username, String email);
}
package com.example.springbootmultijpa.repository.test2;
import com.example.springbootmultijpa.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserTest2Repository extends JpaRepository<User, Long> {
User findById(long id);
User findByUserName(String userName);
User findByUserNameOrEmail(String username, String email);
}
9.6 启动类
package com.example.springbootmultijpa;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootMultiJpaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootMultiJpaApplication.class, args);
}
}
9.7 测试
package com.example.springbootmultijpa.repository;
import com.example.springbootmultijpa.model.User;
import com.example.springbootmultijpa.repository.test1.UserTest1Repository;
import com.example.springbootmultijpa.repository.test2.UserTest2Repository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.text.DateFormat;
import java.util.Date;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserRepositoryTests {
@Resource
private UserTest1Repository userTest1Repository;
@Resource
private UserTest2Repository userTest2Repository;
@Test
public void testSave() throws Exception {
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
String formattedDate = dateFormat.format(date);
userTest1Repository.save(new User("aa", "aa123456", "aa@126.com", "aa", formattedDate));
userTest1Repository.save(new User("bb", "bb123456", "bb@126.com", "bb", formattedDate));
userTest2Repository.save(new User("cc", "cc123456", "cc@126.com", "cc", formattedDate));
}
@Test
public void testDelete() throws Exception {
userTest1Repository.deleteAll();
userTest2Repository.deleteAll();
}
@Test
public void testBaseQuery() {
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
String formattedDate = dateFormat.format(date);
User user = new User("ff", "ff123456", "ff@126.com", "ff", formattedDate);
userTest1Repository.findAll();
userTest2Repository.findById(3l);
userTest2Repository.save(user);
user.setId(2l);
userTest1Repository.delete(user);
userTest1Repository.count();
userTest2Repository.findById(3l);
}
}
运行testSave()
得到的结果:
运行testBaseQuery()
得到的结果:
运行testDelete()
得到的结果:文章来源:https://www.toymoban.com/news/detail-848165.html
文章来源地址https://www.toymoban.com/news/detail-848165.html
到了这里,关于SpringBoot整合JPA的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!