当前位置:Java -> 使用Spring REST和Spring Data MongoDB构建Spring Boot应用

使用Spring REST和Spring Data MongoDB构建Spring Boot应用

MongoDB 是一个功能强大的开源文档导向型数据库管理系统,以其灵活性、可扩展性和广泛的特性而闻名。它是 NoSQL 数据库系统族的一部分,旨在处理大量数据并提供高性能、高可用性和易扩展性。MongoDB 以键值对中 JSON 类似的文档存储数据,这使得 Java Spring Boot 能够在代码中利用 JSON 结构

Spring Boot 与 MongoDB

我们可能会遇到一些情况,我们会在 Spring Boot 中使用 SQL 数据库,但为了在 Spring Boot 中利用 MongoDB,Spring Data MongoDB 提供了轻量级的存储库数据访问和对 MongoDB 数据库的支持,从而降低了代码的复杂性。

假设您对 MongoDB 有相当不错的了解,我们将快速了解如何使用 Spring Data MongoDB 构建 Spring Boot 应用。

先决条件

使用 Spring REST 和 Spring Data MongoDB 创建 Spring Boot 应用的 6 个步骤

在本文中,我使用了 MongoDB Atlas 数据库,这是一个多云开发者数据库服务,允许您在云上创建和维护数据库,而且是免费的。我还使用了 MongoDB Compass,这是一个可视化数据库的 GUI 工具。如果您没有 MongoDB Atlas 的帐户,可以免费试用。

步骤 1:使用 Spring Initializr 创建 Spring Boot 应用

首先,您需要使用 Spring Initializr 创建一个 Spring Boot 应用,它会根据您选择的依赖项生成一个 Spring Boot 项目。一旦您选择了如下图片中的字段,点击 Generate,并将提取的项目导入到您的 IDE 中。

Generate spring boot application using Spring initializer


项目结构:

Project structure with "Student" highlighted


步骤 2:配置数据库

为了在 Spring Boot 应用中配置 MongoDB,我们将在 src/main/resources/application.properties 文件中添加数据库 URL,如下所示:

spring.data.mongodb.uri = mongodb+srv://username:password@student.port.mongodb.net/student


模型:

MongoDB 是一个非关系型、文档导向型数据库。我们创建了一个 StudentAddress 的 Java 模型用于存储对象。使用 @Document 注解来提供自定义的集合名称,@Field  用于提供对象的自定义键名。

在下面的代码中,我们创建了具有不同数据类型的变量,如 Date、List 等。

Student.java

package com.example.studentmanagementsystem.model;

import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.time.LocalDate;
import java.util.List;

@Document("Student")
public class Student {
    @Id
    @Indexed(unique = true)
    private String id;
    private String name;
    private double cgpa;
    @Field("has_arrears")
    private boolean hasArrears;
    @Field("course_list")
    private List<String> courseList;
    private Address address;
    @Field("enrollment_date")
    @JsonFormat
            (shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
    private LocalDate enrollmentDate;
}


Address.java

package com.example.studentmanagementsystem.model;

import jakarta.persistence.Entity;
import org.springframework.data.mongodb.core.mapping.Field;

@Entity
public class Address {
    private String street;
    private String city;
    private String state;
    private String country;
    @Field("zip_code")
    private String zipcode;
}


步骤 3:创建存储库

我们创建了一个接口 StudentRepository,它继承自 MongoRepository。MongoRepository 是 Spring Data 提供的一个接口,允许预定义的 CRUD 操作和自动映射。CRUD 或 REST 操作实际上就是服务和数据之间以一种持久和结构化的方式进行通信。

Spring @Repository 注解用来指示该类提供对对象的存储、检索、搜索、更新和删除操作,并充当持久层。

让我们创建 findBy 方法从数据库中获取数据,如下面的代码所示:

package com.example.studentmanagementsystem.repository;
import com.example.studentmanagementsystem.model.Student;
import org.springframework.data.mongodb.repository.Aggregation;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import java.time.LocalDate;
import java.util.List;

@Repository
public interface StudentRepository extends MongoRepository<Student, String> {
    List<Student> findByNameAndCgpa(String name, Double cgpa);

    Student findByAddress_City(String city);

    List<Student> findByAddress_CountryOrHasArrears(String country, Boolean hasArrears);

    List<Student> findByEnrollmentDateBetweenOrderByEnrollmentDate(LocalDate startDate, LocalDate endDate);

    List<Student> findByCgpaGreaterThanEqual(Double cgpa);

    String findByNameIgnoreCase(String name);

    List<Student> findByCgpaOrderByNameDesc(Double cgpa, String name);
  
//aggregation example for overall average cgpa
    @Aggregation("{ $group : { _id : null, averageCgpa : { $avg : $cgpa} } }")
    Long avgCgpa();

}


步骤 4:创建服务

为了与 MongoDB 数据库中的数据进行交互,让我们为 Student 存储库创建一个服务层。我们将创建一些方法来利用插入、检索和删除等 CRUD 操作。

package com.example.studentmanagementsystem.service;

import com.example.studentmanagementsystem.model.Student;
import com.example.studentmanagementsystem.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

@Service
public class StudentService {
    @Autowired
    private StudentRepository studentRepo;

    public void addStudentData(Student studentDetails) {
        studentRepo.insert(studentDetails);
    }

    public void addMultipleStudentsData(List<Student> studentsDetail) {
        studentRepo.insert(studentsDetail);
    }

    public List<Student> fetchAllStudentsData() {
        return studentRepo.findAll();
    }

    public Optional<Student> fetchStudentDataById(String id) {
        return studentRepo.findById(id);
    }

    public List<Student> fetchStudentDataByNameAndCgpa(String name, Double cgpa) {
        return studentRepo.findByNameAndCgpa(name, cgpa);
    }

    public Student fetchStudentDataByCity(String city) {
        return studentRepo.findByAddress_City(city);
    }

    public List<Student> fetchStudentDataByCountryOrArrears(String country, Boolean hasArrears) {
        return studentRepo.findByAddress_CountryOrHasArrears(country, hasArrears);
    }

    public List<Student> fetchStudentDataByCgpa(Double cgpa) {
        return studentRepo.findByCgpaGreaterThanEqual(cgpa);
    }

    public List<Student> fetchStudentDataByEnrollmentDate(LocalDate startDate, LocalDate endDate) {
        return studentRepo.findByEnrollmentDateBetweenOrderByEnrollmentDate(startDate, endDate);
    }

    public List<Student> fetchStudentDataByCgpaAndName(Double cgpa, String name) {
        return studentRepo.findByCgpaOrderByNameDesc(cgpa, name);
    }

    public Long fetchAverageCgpa() {
        return studentRepo.avgCgpa();
    }

    public String fetchStudentDataByName(String name) {
        return studentRepo.findByNameIgnoreCase(name);
    }

    public void deleteStudentData(Student studentDetails) {
        studentRepo.insert(studentDetails);
    }

    public void deleteAllStudentData() {
        studentRepo.deleteAll();
    }
}


步骤 5:创建控制器

接下来,为 Student 资源构建 CRUD REST API 调用,以从 MongoDB 数据库中获取、插入或删除资源。

Spring @RestController注解用于创建RESTful Web服务,它结合了@Controller和@ResponseBody注解,使得编写处理方法变得更加简单。

package com.example.studentmanagementsystem.controller;

import com.example.studentmanagementsystem.model.Student;
import com.example.studentmanagementsystem.service.StudentService;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/student")
public class StudentController {
    @Autowired
    private StudentService studentService;

    @PostMapping("/addStudent")
    public void populateStudentData(@RequestBody Student student){
          studentService.addStudentData(student);
    }

    @PostMapping("/addStudentsData")
    public void populateStudentsData(@RequestBody List<Student> students){
        studentService.addMultipleStudentsData(students);
    }

    @GetMapping("/getAllStudentsData")
    public List<Student> fetchAllStudentsData(){
        return studentService.fetchAllStudentsData();
    }

    @GetMapping("/getStudentById/{id}")
    public Optional<Student> fetchStudentDataById(@PathVariable String id){
       return studentService.fetchStudentDataById(id);
    }
    @GetMapping("/getStudentByNameAndCgpa")
    public List<Student> fetchStudentDataByNameAndCgpa(@RequestParam String name, @RequestParam Double cgpa){
        return studentService.fetchStudentDataByNameAndCgpa(name, cgpa);
    }
    @GetMapping("/getStudentByCity/{city}")
    public Student fetchStudentDataByCity(@PathVariable String city){
        return studentService.fetchStudentDataByCity(city);
    }
    @GetMapping("/getStudentByCountryOrArrears")
    public List<Student> fetchStudentDataByCountryOrArrears(@RequestParam String country,@RequestParam Boolean hasArrears){
        return studentService.fetchStudentDataByCountryOrArrears(country, hasArrears);
    }
    @GetMapping("/getStudentByEnrollmentDate")
    public List<Student> fetchStudentDataByEnrollmentDate(@JsonFormat
                                                                      (shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy") LocalDate startDate, @JsonFormat
            (shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy") LocalDate endDate){
        return studentService.fetchStudentDataByEnrollmentDate(startDate, endDate);
    }
    @GetMapping("/getStudentByName")
    public String fetchStudentDataByName(@RequestParam String name){
        return studentService.fetchStudentDataByName(name);
    }
    @GetMapping("/getStudentByCgpa")
    public List<Student> fetchStudentDataByCgpa(@RequestParam Double cgpa){
        return studentService.fetchStudentDataByCgpa(cgpa);
    }
    @GetMapping("/getAvgCgpa")
    public Long fetchStudentAvgCgpa(){
        return studentService.fetchAverageCgpa();
    }
    @DeleteMapping("/deleteStudent")
    public void deleteStudentData(Student student){
        studentService.deleteStudentData(student);
    }

    @DeleteMapping("/deleteAllStudents")
    public void deleteAllStudentsData(){
        studentService.deleteAllStudentData();
    }
}


步骤6:测试

现在,让我们使用Postman测试其中一个API调用,从数据库中获取数据,如下图所示。

下面的HTTP方法返回JSON对象数组中的所有学生信息。

  1. 方法:GET 

        请求URL:http://localhost:8080/student/getAllStudentsData

使用Postman从数据库中获取数据

 

我们构建了一个使用MongoDB数据库的Spring Boot应用程序,并创建了创建、删除和从数据库获取数据的CRUD操作,其中包括了不同的数据获取方式。Spring Data MongoDB帮助我们使用内置方法进行CRUD操作,从而减少了持久层中的代码复杂性。

推荐阅读: 朋友眼中的程序员是什么样子的

本文链接: 使用Spring REST和Spring Data MongoDB构建Spring Boot应用