使用Spring Boot,Hibernate和JPA构建RESTful CRUD服务


CRUD REST服务允许基础资源上的HTTP GET,POST,PUT和DELETE端点。客户端可以通过提供相应的资源标识符,使用这些端点来创建,读取,更新和删除资源。

本教程提供了使用Spring Data JPA和Hibernate在Spring Boot中构建自己的RESTful CRUD服务的分步方法,以对数据库资源执行CRUD操作。

我们将编写一个学生服务,这是Spring Boot REST应用程序的一个示例。该服务允许客户添加新学生,查找学生以及修改或删除任何现有学生。在后端,我们将使用H2数据库来存储学生的信息。

在本教程中,我们将介绍:

  1. 所需的POM依赖关系。
  2. 如何为学生创建实体课。
  3. 如何编写一个Spring Data Repository。
  4. 如何编写具有CRUD API的REST控制器。
  5. 如何测试我们的应用程序。

Maven依赖

为了运行基本的Spring Boot JPA项目,我们需要Web启动程序和data-jpa启动程序依赖项。

<dependencies>
        <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>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

我们还添加了H2数据库依赖关系,它是基于Java的内存数据库。如果默认的Spring Boot在class path上可用,它将默认连接到H2数据库。换句话说,我们不需要为此数据库提供任何连接详细信息。

写一个实体Bean

我们将创建一个Student具有@Entity注释的类,以使其成为实体bean。另外,学生班级具有基本字段,其中Id是自动生成的增量字段。

package com.amitph.spring.tutorials.students.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Data
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long student_id;
    private String firstName;
    private String lastName;
    private int year;
}

我们正在使用Lombok@Data批注,该批注会自动生成此类的所有getter和setter。

创建JPA存储库

接下来,我们将编写一个从扩展的存储库接口JpaRepository。有趣的是,我们没有为此接口添加任何方法,也没有为此提供任何实现类。这是因为Spring Boot Data JPA自动实现了此接口。

package com.amitph.spring.tutorials.students.entity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
}

写一个休息控制器

接下来,我们将为学生编写一个Rest Controller并提供所有CRUD方法。

package com.amitph.spring.tutorials.students;
import com.amitph.spring.tutorials.students.entity.StudentRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
public class StudentsController {
    private final StudentRepository studentRepository;
}

编写POST方法

POST方法用于创建新资源。因此,我们正在使用它来一次创建一个新的学生。

@PostMapping("/students")
public void postStudent(@RequestBody StudentDto studentDto) {
    Student student = new Student();
    student.setFirstName(studentDto.getFirstName());
    student.setLastName(studentDto.getLastName());
    student.setYear(studentDto.getYear());
    studentRepository.save(student);
}

用户将发送带有学生详细信息的POST请求。Spring Boot@RequestBody注释将请求主体参数映射到StudentDto对象中。接下来,我们创建一个实体bean的新实例并设置所有字段。但是,我们没有设置该id字段,因为它是由Hibernate自动生成的。最后,我们要求存储库保存新创建的实体bean。

编写PUT方法

用户发送一个PUT请求以修改现有资源。因此,我们的API端点在请求路径中需要一个学生ID。

@PutMapping("/students/{id}")
public void putStudent(@PathVariable long id, @RequestBody StudentDto studentDto) {
    Student student = new Student();
    student.setStudent_id(id);
    student.setFirstName(studentDto.getFirstName());
    student.setLastName(studentDto.getLastName());
    student.setYear(studentDto.getYear());
    studentRepository.save(student);
}

我们正在将请求主体映射到一个StudentDto对象中。使用该代码,我们将Student使用提供的ID创建一个新实体。因为我们使用相同的ID,所以Hibernate不会在表中创建新记录。相反,它将更新现有的一个。

编写一个DELETE方法

编写DELETE非常简单。我们希望在路径变量中出现一个学生ID。因此,我们可以要求存储库使用其ID删除特定资源。

@DeleteMapping("/students/{id}")
public void deleteStudent(@PathVariable long id) {
    studentRepository.deleteById(id);
}

编写GET方法

接下来是GET方法的示例,其中用户可以将Student Id作为路径变量传递来获取Student。StudentNotFoundException如果未找到具有特定ID的学生,则端点引发。

@GetMapping("/students/{id}")
public Student getStudent(@PathVariable long id) {
    return studentRepository
          .findById(id)
          .orElseThrow(StudentNotFoundException::new);
}

用户可能想获取学生的完整列表。为此,我们将创建另一个GET端点,该端点是通用的,并返回Student列表。

@GetMapping("/students")
public List<Student> getStudents() {
    return studentRepository.findAll();
}

处理未找到的异常

在上述端点中,我们抛出一个StudentNotFoundException。此类是的扩展RuntimeException,它HttpStatus.NOT_FOUND作为响应返回(404)。

package com.amitph.spring.tutorials.students;
import org.springframework.web.bind.annotation.ResponseStatus;
import static org.springframework.http.HttpStatus.NOT_FOUND;
@ResponseStatus(NOT_FOUND)
public class StudentNotFoundException extends RuntimeException {
    public StudentNotFoundException() {
        super();
    }
}

如果您不熟悉ResponseStatus,请阅读Spring Rest Service异常处理。

运行并测试 让我们运行该应用程序并测试所有端点。为此,我们正在使用curl,但是,您也可以使用Postman或任何类似的工具。

创建一个新学生

~ curl --location --request POST 'localhost:8080/students' \
--header 'Content-Type: application/json' \
--data-raw '{
    "firstName" : "Strong",
    "lastName" : "Belwas",
    "year" :2025
}'

修改学生

在下一个示例中,我们将更改ID为2的学生的名字。

~ curl --location --request PUT 'localhost:8080/students/2' \
--header 'Content-Type: application/json' \
--data-raw '{
    "firstName" : "JORY",
    "lastName" : "CASSEL",
    "year" : 2020
}'

检索学生

我们将通过传递Id 2来对学生调用GET。下一行的输出显示正确返回了相应的Student。

~ curl --location --request GET 'localhost:8080/students/2'
{"student_id":2,"firstName":"JORY","lastName":"CASSEL","year":2020}%

我们也可以通过省略id的path变量来获取所有学生。

curl --location --request GET 'localhost:8080/students/'
[{ “ student_id”:1,“ firstName”:“ Strong”,“ lastName”:“ Belwas”,“ year”:2025},{ “ student_id”:2,“ firstName”:“ JORY”,“ lastName”:“ CASSEL”,“ year”:2020},{ “ student_id”:3,“ firstName”:“ Arthur”,“ lastName”:“ Dayne”,“ year”:2022}]]

删除学生

要删除学生,我们将执行传递ID的DELETE请求作为路径变量。

~ curl --location --request DELETE 'localhost:8080/students/2'

概括

在本动手教程中,我们学习了如何 使用Hibernate和JPA编写Spring Boot CRUD REST API服务。为此,我们编写了最重要的组件以及各个HTTP请求处理程序。最后,我们通过执行POST,PUT,GET和DELETE端点测试了我们的API。


原文链接:http://codingdict.com