Spring Boot Jpa 简明教程
Spring Boot JPA - Overview
Spring Boot JPA - Environment Setup
本章将指导您如何准备开发环境,以便使用 Spring Boot Framework 开始您的工作。它还将教您在设置 Spring Boot Framework 之前如何设置机器上的 JDK、Eclipse -
Step 1 - Setup Java Development Kit (JDK)
Java SE 可免费下载。若要下载 click here,请下载与你的操作系统兼容的版本。
按照说明下载 Java,并运行 .exe 在你的计算机上安装 Java。在计算机上安装 Java 后,你需要设置环境变量来指向正确的安装目录。
Setting Up the Path for Windows 2000/XP
假设你已将 Java 安装在 c:\Program Files\java\jdk 目录中 −
-
右键单击“我的电脑”,然后选择“属性”。
-
单击“高级”选项卡下的“环境变量”按钮。
-
现在,编辑“Path”变量,并在其末尾添加 Java 可执行目录的路径。例如,如果路径当前设置为 C:\Windows\System32 ,则按如下方式进行编辑 C:\Windows\System32;c:\Program Files\java\jdk\bin 。
Setting Up the Path for Windows 95/98/ME
假设你已将 Java 安装在 c:\Program Files\java\jdk 目录中 −
-
编辑“C:\autoexec.bat”文件,并在结尾处添加以下行 − SET PATH=%PATH%;C:\Program Files\java\jdk\bin
Setting Up the Path for Linux, UNIX, Solaris, FreeBSD
环境变量 PATH 应设置为指向已安装 Java 二进制文件的位置。如果你在这方面遇到问题,请参阅 shell 文档。
例如,如果你使用 bash 作为你的 shell,那么你将在 .bashrc 的末尾添加以下行 −
或者,如果你使用诸如 Borland JBuilder、Eclipse、IntelliJ IDEA 或 Sun ONE Studio 这样的集成开发环境 (IDE),则必须编译并运行一个简单程序来确认 IDE 知道你在何处安装了 Java。否则,你必须按照 IDE 文档中给出的内容执行正确的设置。
Step 2 - Setup Eclipse IDE
本教程中的所有示例都是使用 Eclipse IDE 编写的。因此,我们建议你应该在你机器上安装 Eclipse 的最新版本。
要安装 Eclipse IDE,请从 www.eclipse.org/downloads/ 下载最新的 Eclipse 二进制文件。下载安装文件后,将二进制分发解压缩到合适的目录中。例如,在 Windows 中的 C:\eclipse 或 Linux/Unix 中的 /usr/local/eclipse 中,最后适当设置 PATH 变量。
可以通过在 Windows 机器上执行以下命令启动 Eclipse,或者你只需双击 eclipse.exe
%C:\eclipse\eclipse.exe
可以通过在 Unix(Solaris、Linux 等)机器上执行以下命令启动 Eclipse −
$/usr/local/eclipse/eclipse
成功启动后,如果一切正常,它应该显示以下结果 −
Step 3 - Setup m2eclipse
M2Eclipse 是一个 Eclipse 插件,它对于将 Apache Maven 集成到 Eclipse IDE 中非常有用。我们在本教程中使用 maven 来构建 spring boot 项目,并使用 m2eclipse 在 eclipse 内运行示例。
使用 Eclipse IDE 中的“安装新软件”对话框安装最新的 M2Eclipse 版本,并将其指向此 p2 仓库 -
Step 3 - Setup Spring Boot Project
现在,如果一切正常,则可以继续设置 Spring Boot。以下是下载和在机器上安装 Spring Boot 项目的简单步骤。
-
转到 Spring 初始化器链接以创建 Spring Boot 项目, https://start.spring.io/ 。
-
选择项目作为 Maven Project 。
-
Select language as Java.
-
选择 Spring Boot 版本作为 2.5.3 。
-
将项目元数据设定为 - 组为 com.tutorialspoint ,工件为 springboot-h2 ,名称为 springboot-h2 ,描述为 Demo project for Spring Boot and H2 Database ,包名为 com.tutorialspoint.springboot-h2 。
-
Select packaging as Jar.
-
Select java as 11.
-
添加依赖关系为 Spring Web, Spring Data JPA, H2 Database and Spring Boot DevTools 。
现在点击生成按钮来生成项目结构。
一旦基于 maven 的 Spring Boot 项目下载完成,然后将 maven 项目导入 eclipse,其余操作由 eclipse 处理。它将下载 maven 依赖关系,并构建项目以使之可以进行进一步的开发。
Step 4 - POSTMAN for REST APIs Testing
POSTMAN 是一款用来测试基于 REST 的 API 的有用工具。要安装 POSTMAN,可从 www.postman.com/downloads/ 下载最新的 POSTMAN 二进制文件。下载完可安装文件后,按照说明进行安装并使用。
Spring Boot JPA - Architecture
Java 持久化 API 是一个将业务实体存储为关系实体的源。它展示了如何将一个普通旧 Java 对象 (POJO) 定义为实体,以及如何通过关系管理实体。
Class Level Architecture
下图展示了 JPA 的类级架构。它展示了 JPA 的核心类和接口。
下表描述了上述架构中显示的每个单元。
Sr.No |
Units & Description |
1 |
EntityManagerFactory 它是 EntityManager 的工厂类。它创建和管理多个 EntityManager 实例。 |
2 |
EntityManager 它是一个接口,管理对象上的持久性操作。它如同 Query 实例的工厂。 |
3 |
Entity 实体是持久性对象,存储为数据库中的记录。 |
4 |
EntityTransaction 它与 EntityManager 存在一对一的关系。对于每个 EntityManager,操作由 EntityTransaction 类维护。 |
5 |
Persistence 此类包含获取 EntityManagerFactory 实例的静态方法。 |
6 |
Query 此接口由每个 JPA 供应商实现,以获取满足条件的关系对象。 |
上述类和接口用于将实体作为记录存储在数据库中。它们通过减少程序员为将数据存储到数据库中而编写代码的工作量来为他们提供帮助,以便他们可以专注于诸如编写映射类与数据库表的代码之类的更重要的活动。
JPA Class Relationships
在上述架构中,类和接口之间的关系属于 javax.persistence 包。下图显示了它们之间的关系。
-
EntityManagerFactory 和 EntityManager 之间的关系为 one-to-many 。它是 EntityManager 实例的工厂类。
-
EntityManager 和 EntityTransaction 之间的关系为 one-to-one 。对于每个 EntityManager 操作,都有一个 EntityTransaction 实例。
-
EntityManager 和 Query 之间的关系为 one-to-many 。可以使用一个 EntityManager 实例执行许多查询。
-
EntityManager 和 Entity 之间的关系为 one-to-many 。一个 EntityManager 实例可以管理多个 Entity。
Spring Boot JPA vs Hibernate
JPA Vs Hibernate
下表总结了 JPA 和 Hibernate 之间的差异。
Category |
JPA |
Hibernate |
Type |
JPA 是一个规范,并定义了使用 Java 对象管理关系数据库数据的方法。 |
Hibernate 是 JPA 的一种实现。它是一种 ORM 工具,用于将 Java 对象持久化到关系数据库中。 |
Package |
JPA uses javax.persistence package. |
Hibernate uses org.hibernate package. |
Factory |
JPA 使用 EntityManagerFactory 接口获得实体管理器以持久化对象。 |
Hibernate 使用 SessionFactory 接口来创建会话对象,该对象随后用于持久化对象。 |
CRUD Operations |
JPA 使用 EntityManager 接口来创建/读取/删除操作,并维护持久性上下文。 |
Hibernate 使用 Session 接口来创建/读取/删除操作,并维护持久性上下文。 |
Language |
JPA 使用 JPQL(Java 持久性查询语言)作为面向对象查询语言进行数据库操作。 |
Hibernate 使用 HQL(Hibernate 查询语言)作为面向对象查询语言进行数据库操作。 |
Spring Boot JPA - Application Setup
与上一章 Environment Setup 中一样,我们已在 Eclipse 中导入了已生成的 Spring Boot 项目。现在,让我们在 src/main/java 文件夹中创建以下结构。
-
com.tutorialspoint.controller.EmployeeController ——一个REST基于控制器实现REST基于API。
-
com.tutorialspoint.entity.Employee ——一个实体类表示数据库中对应的表。
-
com.tutorialspoint.repository.EmployeeRepository ——一个存储库接口来执行crud操作库。
-
com.tutorialspoint.service.EmployeeService ——一个服务类来执行业务操作库函数。
-
com.tutorialspoint.springbooth2.SprintBootH2Application ——一个SpringBoot应用程序类。
SprintBootH2Application类已存在。我们须创建上述包和相关类和接口如下所示——
Entity - Entity.java
以下为Employee的默认代码。它表示一个带id,name,age和email列的Employee表。
package com.tutorialspoint.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table
public class Employee {
@Id
@Column
private int id;
@Column
private String name;
@Column
private int age;
@Column
private String email;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Repository - EmployeeRepository.java
以下为实现上述实体创建CRUD操作的存储库的默认代码,Employee。
package com.tutorialspoint.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.tutorialspoint.entity.Employee;
@Repository
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
}
Service - EmployeeService.java
以下为实现库函数操作的服务的默认代码。
package com.tutorialspoint.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.tutorialspoint.entity.Employee;
import com.tutorialspoint.repository.EmployeeRepository;
@Service
public class EmployeeService {
@Autowired
EmployeeRepository repository;
public Employee getEmployeeById(int id) {
return repository.findById(id).get();
}
public List<Employee> getAllEmployees(){
List<Employee> employees = new ArrayList<Employee>();
repository.findAll().forEach(employee -> employees.add(employee));
return employees;
}
public void saveOrUpdate(Employee employee) {
repository.save(employee);
}
public void deleteEmployeeById(int id) {
repository.deleteById(id);
}
}
Controller - EmployeeController.java
以下为实现REST API的控制器的默认代码。
package com.tutorialspoint.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.tutorialspoint.entity.Employee;
import com.tutorialspoint.service.EmployeeService;
@RestController
@RequestMapping(path = "/emp")
public class EmployeeController {
@Autowired
EmployeeService employeeService;
@GetMapping("/employees")
public List<Employee> getAllEmployees(){
return employeeService.getAllEmployees();
}
@GetMapping("/employee/{id}")
public Employee getEmployee(@PathVariable("id") int id) {
return employeeService.getEmployeeById(id);
}
@DeleteMapping("/employee/{id}")
public void deleteEmployee(@PathVariable("id") int id) {
employeeService.deleteEmployeeById(id);
}
@PostMapping("/employee")
public void addEmployee(@RequestBody Employee employee) {
employeeService.saveOrUpdate(employee);
}
@PutMapping("/employee")
public void updateEmployee(@RequestBody Employee employee) {
employeeService.saveOrUpdate(employee);
}
}
Application - SprintBootH2Application.java
以下为用于使用上述类的Application的更新代码。
package com.tutorialspoint.sprintbooth2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@ComponentScan({"com.tutorialspoint.controller","com.tutorialspoint.service"})
@EntityScan("com.tutorialspoint.entity")
@EnableJpaRepositories("com.tutorialspoint.repository")
@SpringBootApplication
public class SprintBootH2Application {
public static void main(String[] args) {
SpringApplication.run(SprintBootH2Application.class, args);
}
}
Run/Debug Configuration
在eclipse中创建以下 maven configuration 来运行带目标 spring-boot:run 的springboot应用程序。此配置将有助于运行REST API,我们可以使用POSTMAN对其进行测试。
Run the application
在 Eclipse 中,运行 Employee Application 配置。Eclipse 控制台将显示类似的输出。
[INFO] Scanning for projects...
...
2021-07-24 20:51:14.823 INFO 9760 --- [restartedMain] c.t.s.SprintBootH2Application:
Started SprintBootH2Application in 7.353 seconds (JVM running for 8.397)
服务器启动并运行后,使用 Postman 先执行 POST 请求以添加记录。
在 POSTMAN 中设置以下参数。
-
HTTP Method - POST
-
正文 - An employee JSON
{
"id": "1",
"age": "35",
"name": "Julie",
"email": "julie@gmail.com"
}
单击发送按钮并检查响应状态是否为 OK。现在执行 GET 请求以获取所有记录。
在 POSTMAN 中设置以下参数。
-
HTTP Method - GET
单击发送按钮并验证响应。
[{
"id": "1",
"age": "35",
"name": "Julie",
"email": "julie@gmail.com"
}]
Spring Boot JPA - Unit Test Repository
要测试存储库,我们需要以下注释和类:
-
@ExtendWith(SpringExtension.class) ——使用SpringExtension类将类标记为以测试用例运行。
-
@SpringBootTest(classes = SprintBootH2Application.class) - 配置 Spring Boot 应用程序。
-
@Transactional - 用于标记存储库以执行 CRUD 操作。
-
@Autowired private EmployeeRepository employeeRepository - 要测试的 EmployeeRepository 对象。
Example
以下是 EmployeeRepositoryTest 的完整代码。
package com.tutorialspoint.repository;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.ArrayList;
import java.util.List;
import javax.transaction.Transactional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.tutorialspoint.entity.Employee;
import com.tutorialspoint.sprintbooth2.SprintBootH2Application;
@ExtendWith(SpringExtension.class)
@Transactional
@SpringBootTest(classes = SprintBootH2Application.class)
public class EmployeeRepositoryTest {
@Autowired
private EmployeeRepository employeeRepository;
@Test
public void testFindById() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee result = employeeRepository.findById(employee.getId()).get();
assertEquals(employee.getId(), result.getId());
}
@Test
public void testFindAll() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findAll().forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
@Test
public void testSave() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee found = employeeRepository.findById(employee.getId()).get();
assertEquals(employee.getId(), found.getId());
}
@Test
public void testDeleteById() {
Employee employee = getEmployee();
employeeRepository.save(employee);
employeeRepository.deleteById(employee.getId());
List<Employee> result = new ArrayList<>();
employeeRepository.findAll().forEach(e -> result.add(e));
assertEquals(result.size(), 0);
}
private Employee getEmployee() {
Employee employee = new Employee();
employee.setId(1);
employee.setName("Mahesh");
employee.setAge(30);
employee.setEmail("mahesh@test.com");
return employee;
}
}
Spring Boot JPA - Repository methods
现在让我们分析在已创建的存储库接口中可用的方法。
Repository - EmployeeRepository.java
以下为实现上述实体创建CRUD操作的存储库的默认代码,Employee。
package com.tutorialspoint.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.tutorialspoint.entity.Employee;
@Repository
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
}
现在,此存储库默认包含以下方法。
Sr.No |
Method & Description |
1 |
count(): long 返回可用的实体数量。 |
2 |
delete(Employee entity): void 删除实体。 |
3 |
deleteAll():void deletes all the entities. |
4 |
deleteAll(Iterable< extends Employee > entities):void 删除作为参数传递的实体。 |
5 |
deleteAll(Iterable< extends Integer > ids):void 使用作为参数传递的 ID 来删除实体。 |
6 |
existsById(Integer id):boolean 使用其 ID 检查实体是否存在。 |
7 |
findAll():Iterable< Employee > 返回所有实体。 |
8 |
findAllByIds(Iterable< Integer > ids):Iterable< Employee > 返回使用作为参数传递的 ID 标识的所有实体。 |
9 |
findById(Integer id):Optional< Employee > 返回使用 ID 标识的实体。 |
10 |
save(Employee entity): Employee 保存实体并返回更新后的实体。 |
11 |
saveAll(Iterable< Employee> entities): Iterable< Employee> 会保存所有传递的实体并返回更新的实体。 |
Spring Boot JPA - Custom methods
我们在 JPA Methods 章节中检查了存储库中默认提供的这些方法。现在我们添加一个方法,并对其进行测试。
Repository - EmployeeRepository.java
Example
添加一个通过名字找到员工的方法。
package com.tutorialspoint.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.tutorialspoint.entity.Employee;
@Repository
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
public List<Employee> findByName(String name);
public List<Employee> findByAge(int age);
}
现在,Spring JPA 会根据我们遵循基于属性的命名方式自动创建一个以上方法的实现。让我们在 test 文件中添加测试用例,从而测试所添加的方法。以下文件中的最后两个方法测试了所添加的自定义方法。
以下是 EmployeeRepositoryTest 的完整代码。
package com.tutorialspoint.repository;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.ArrayList;
import java.util.List;
import javax.transaction.Transactional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.tutorialspoint.entity.Employee;
import com.tutorialspoint.sprintbooth2.SprintBootH2Application;
@ExtendWith(SpringExtension.class)
@Transactional
@SpringBootTest(classes = SprintBootH2Application.class)
public class EmployeeRepositoryTest {
@Autowired
private EmployeeRepository employeeRepository;
@Test
public void testFindById() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee result = employeeRepository.findById(employee.getId()).get();
assertEquals(employee.getId(), result.getId());
}
@Test
public void testFindAll() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findAll().forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
@Test
public void testSave() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee found = employeeRepository.findById(employee.getId()).get();
assertEquals(employee.getId(), found.getId());
}
@Test
public void testDeleteById() {
Employee employee = getEmployee();
employeeRepository.save(employee);
employeeRepository.deleteById(employee.getId());
List<Employee> result = new ArrayList<>();
employeeRepository.findAll().forEach(e -> result.add(e));
assertEquals(result.size(), 0);
}
private Employee getEmployee() {
Employee employee = new Employee();
employee.setId(1);
employee.setName("Mahesh");
employee.setAge(30);
employee.setEmail("mahesh@test.com");
return employee;
}
@Test
public void testFindByName() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findByName(employee.getName()).forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
@Test
public void testFindByAge() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findByAge(employee.getAge()).forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
}
Spring Boot JPA - Named Queries
有时会出现需要自定义查询来完成某个测试用例的情况。我们可以使用 @NamedQuery 注解指定实体类中的命名查询,然后再在存储库中声明该方法。以下是示例。
我们在 JPA Custom Methods 章节中存储库中添加了自定义方法。现在,我们使用 @NamedQuery 添加另一个方法,并对其进行测试。
Entity - Entity.java
以下为Employee的默认代码。它表示一个带id,name,age和email列的Employee表。
package com.tutorialspoint.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
@Entity
@Table
@NamedQuery(name = "Employee.findByEmail",
query = "select e from Employee e where e.email = ?1")
public class Employee {
@Id
@Column
private int id;
@Column
private String name;
@Column
private int age;
@Column
private String email;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Repository - EmployeeRepository.java
添加一个通过名字和年龄找到员工的方法。
package com.tutorialspoint.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.tutorialspoint.entity.Employee;
@Repository
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
public List<Employee> findByName(String name);
public List<Employee> findByAge(int age);
public Employee findByEmail(String email);
}
现在,Spring JPA 将使用命名查询中提供的查询,自动创建以上方法的实现。让我们在 test 文件中添加测试用例,从而测试所添加的方法。以下文件中的最后两个方法测试了所添加的命名查询方法。
以下是 EmployeeRepositoryTest 的完整代码。
package com.tutorialspoint.repository;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.ArrayList;
import java.util.List;
import javax.transaction.Transactional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.tutorialspoint.entity.Employee;
import com.tutorialspoint.sprintbooth2.SprintBootH2Application;
@ExtendWith(SpringExtension.class)
@Transactional
@SpringBootTest(classes = SprintBootH2Application.class)
public class EmployeeRepositoryTest {
@Autowired
private EmployeeRepository employeeRepository;
@Test
public void testFindById() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee result = employeeRepository.findById(employee.getId()).get();
assertEquals(employee.getId(), result.getId());
}
@Test
public void testFindAll() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findAll().forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
@Test
public void testSave() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee found = employeeRepository.findById(employee.getId()).get();
assertEquals(employee.getId(), found.getId());
}
@Test
public void testDeleteById() {
Employee employee = getEmployee();
employeeRepository.save(employee);
employeeRepository.deleteById(employee.getId());
List<Employee> result = new ArrayList<>();
employeeRepository.findAll().forEach(e -> result.add(e));
assertEquals(result.size(), 0);
}
private Employee getEmployee() {
Employee employee = new Employee();
employee.setId(1);
employee.setName("Mahesh");
employee.setAge(30);
employee.setEmail("mahesh@test.com");
return employee;
}
@Test
public void testFindByName() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findByName(employee.getName()).forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
@Test
public void testFindByAge() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findByAge(employee.getAge()).forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
@Test
public void testFindByEmail() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee result = employeeRepository.findByEmail(employee.getEmail());
assertNotNull(result);
}
}
Spring Boot JPA - Custom Query
有时会出现需要自定义查询来完成某个测试用例的情况。我们可以使用 @Query 注解在存储库内指定一个查询。以下是示例。在此示例中,我们使用 Java 持久化查询语言 (JPQL)。
我们在 JPA Named Query 章节中存储库中添加了名为查询的自定义方法。现在,我们使用 @Query 添加另一个方法,并对其进行测试。
Repository - EmployeeRepository.java
添加一个按名字对员工列表进行排序的方法。
package com.tutorialspoint.repository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.tutorialspoint.entity.Employee;
@Repository
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
public List<Employee> findByName(String name);
public List<Employee> findByAge(int age);
public Employee findByEmail(String email);
@Query(value = "SELECT e FROM Employee e ORDER BY name")
public List<Employee> findAllSortedByName();
}
让我们在 test 文件中添加测试用例,从而测试所添加的方法。以下文件中的最后两个方法测试了所添加的自定义查询方法。
以下是 EmployeeRepositoryTest 的完整代码。
package com.tutorialspoint.repository;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.ArrayList;
import java.util.List;
import javax.transaction.Transactional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.tutorialspoint.entity.Employee;
import com.tutorialspoint.sprintbooth2.SprintBootH2Application;
@ExtendWith(SpringExtension.class)
@Transactional
@SpringBootTest(classes = SprintBootH2Application.class)
public class EmployeeRepositoryTest {
@Autowired
private EmployeeRepository employeeRepository;
@Test
public void testFindById() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee result = employeeRepository.findById(employee.getId()).get();
assertEquals(employee.getId(), result.getId());
}
@Test
public void testFindAll() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findAll().forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
@Test
public void testSave() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee found = employeeRepository.findById(employee.getId()).get();
assertEquals(employee.getId(), found.getId());
}
@Test
public void testDeleteById() {
Employee employee = getEmployee();
employeeRepository.save(employee);
employeeRepository.deleteById(employee.getId());
List<Employee> result = new ArrayList<>();
employeeRepository.findAll().forEach(e -> result.add(e));
assertEquals(result.size(), 0);
}
private Employee getEmployee() {
Employee employee = new Employee();
employee.setId(1);
employee.setName("Mahesh");
employee.setAge(30);
employee.setEmail("mahesh@test.com");
return employee;
}
@Test
public void testFindByName() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findByName(employee.getName()).forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
@Test
public void testFindByAge() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findByAge(employee.getAge()).forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
@Test
public void testFindByEmail() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee result = employeeRepository.findByEmail(employee.getEmail());
assertNotNull(result);
}
@Test
public void testFindAllSortedByName() {
Employee employee = getEmployee();
Employee employee1 = new Employee();
employee1.setId(2);
employee1.setName("Aarav");
employee1.setAge(20);
employee1.setEmail("aarav@test.com");
employeeRepository.save(employee);
employeeRepository.save(employee1);
List<Employee> result = employeeRepository.findAllSortedByName();
assertEquals(employee1.getName(), result.get(0).getName());
}
}
Spring Boot JPA - Native Query
有时会出现需要自定义本机查询来完成某个测试用例的情况。我们可以使用 @Query 注解在存储库内指定一个查询。以下是示例。在此示例中,我们使用本机查询,并在 Query 注解中设置 nativeQuery=true 属性,将查询标记为本机查询。
我们在 JPA Custom Query 章节中存储库中添加了自定义方法。现在,我们使用本机查询添加另一个方法,并对其进行测试。
Repository - EmployeeRepository.java
添加一个按名字对员工列表进行排序的方法。
package com.tutorialspoint.repository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.tutorialspoint.entity.Employee;
@Repository
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
public List<Employee> findByName(String name);
public List<Employee> findByAge(int age);
public Employee findByEmail(String email);
@Query(value = "SELECT e FROM Employee e ORDER BY name")
public List<Employee> findAllSortedByName();
@Query(value = "SELECT * FROM Employee ORDER BY name", nativeQuery = true)
public List<Employee> findAllSortedByNameUsingNative();
}
让我们在 test 文件中添加测试用例,从而测试所添加的方法。以下文件中的最后两个方法测试了所添加的自定义查询方法。
Example
以下是 EmployeeRepositoryTest 的完整代码。
package com.tutorialspoint.repository;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.ArrayList;
import java.util.List;
import javax.transaction.Transactional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.tutorialspoint.entity.Employee;
import com.tutorialspoint.sprintbooth2.SprintBootH2Application;
@ExtendWith(SpringExtension.class)
@Transactional
@SpringBootTest(classes = SprintBootH2Application.class)
public class EmployeeRepositoryTest {
@Autowired
private EmployeeRepository employeeRepository;
@Test
public void testFindById() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee result = employeeRepository.findById(employee.getId()).get();
assertEquals(employee.getId(), result.getId());
}
@Test
public void testFindAll() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findAll().forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
@Test
public void testSave() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee found = employeeRepository.findById(employee.getId()).get();
assertEquals(employee.getId(), found.getId());
}
@Test
public void testDeleteById() {
Employee employee = getEmployee();
employeeRepository.save(employee);
employeeRepository.deleteById(employee.getId());
List<Employee> result = new ArrayList<>();
employeeRepository.findAll().forEach(e -> result.add(e));
assertEquals(result.size(), 0);
}
private Employee getEmployee() {
Employee employee = new Employee();
employee.setId(1);
employee.setName("Mahesh");
employee.setAge(30);
employee.setEmail("mahesh@test.com");
return employee;
}
@Test
public void testFindByName() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findByName(employee.getName()).forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
@Test
public void testFindByAge() {
Employee employee = getEmployee();
employeeRepository.save(employee);
List<Employee> result = new ArrayList<>();
employeeRepository.findByAge(employee.getAge()).forEach(e -> result.add(e));
assertEquals(result.size(), 1);
}
@Test
public void testFindByEmail() {
Employee employee = getEmployee();
employeeRepository.save(employee);
Employee result = employeeRepository.findByEmail(employee.getEmail());
assertNotNull(result);
}
@Test
public void testFindAllSortedByName() {
Employee employee = getEmployee();
Employee employee1 = new Employee();
employee1.setId(2);
employee1.setName("Aarav");
employee1.setAge(20);
employee1.setEmail("aarav@test.com");
employeeRepository.save(employee);
employeeRepository.save(employee1);
List<Employee> result = employeeRepository.findAllSortedByName();
assertEquals(employee1.getName(), result.get(0).getName());
}
@Test
public void testFindAllSortedByNameUsingNative() {
Employee employee = getEmployee();
Employee employee1 = new Employee();
employee1.setId(2);
employee1.setName("Aarav");
employee1.setAge(20);
employee1.setEmail("aarav@test.com");
employeeRepository.save(employee);
employeeRepository.save(employee1);
List<Employee> result = employeeRepository.findAllSortedByNameUsingNative();
assertEquals(employee1.getName(), result.get(0).getName());
}
}