Spring Boot Application With Spring REST and Spring Data MongoDB
In this article, we will create a simple Spring Boot application that performs CRUD operations with Spring REST and MongoDB.
Join the DZone community and get the full member experience.
Join For FreeMongoDB is a powerful, open-source, document-oriented database management system known for its flexibility, scalability, and wide range of features. It's part of the NoSQL family of database systems, designed to handle large volumes of data and to provide high performance, high availability, and easy scalability. MongoDB stores data in JSON-like documents in key-value pairs, which allows Java Spring Boot to leverage JSON structure in the code.
Spring Boot With MongoDB
We may come across situations where we use Spring boot with SQL databases, but to leverage MongoDB with Spring boot, Spring Data MongoDB offers lightweight repository data access and support for the MongoDB database, which reduces the complexity of the code.
Assuming that you have quite a good understanding of MongoDB, we will take a quick look at building a Spring Boot application with Spring Data MongoDB.
Prerequisites
- Java
- IDE of your choice
6 Steps to Creating a Spring Boot Application With Spring REST and Spring Data MongoDB
In this article, I have used the MongoDB Atlas database, which is a multi-cloud developer database service that allows you to create and maintain databases on the cloud, free of cost. I also used MongoDB Compass, a GUI tool to visualize the database. If you don't have an account for MongoDB Atlas, you can try it for free.
Step 1: Create a Spring Boot Application With Spring Initializer
First, you'll want to create a Spring Boot application using Spring Initializr, which generates a Spring Boot project with selected dependencies. Once you have selected the fields as shown in the image below, click on Generate, and import the extracted project in your IDE.
Project Structure:
Step 2: Configure the Database
To configure MongoDB in the Spring boot application, we are going to add the database URL in the src/main/resources/application.properties file as shown below:
spring.data.mongodb.uri = mongodb+srv://username:password@student.port.mongodb.net/student
Model:
MongoDB is a non-relational, document-oriented database. We have created a Student and Address Java model to store objects. @Document annotation is used to provide the custom collection name, and @Field is used to provide the custom key name for the object.
In the below code, we have created an example of variables with different data types like Date, List, etc.
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;
}
Step 3: Create the Repository
We have created an interface StudentRepository, which extends to MongoRepository. MongoRepository is an interface provided by Spring Data that allows pre-defined CRUD operations and automatic mapping. CRUD or REST operations are nothing but communication between services and data in a persistent and structured way.
Spring @Repository annotation is used to indicate that the class provides the mechanism for storage, retrieval, search, update, and delete operations on objects and acts as the persistence layer.
Let's create findBy methods to fetch data from the database as shown in the code below:
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();
}
Step 4: Create a Service
Let's build a service layer for the Student repository in order to communicate with the data in the MongoDB database. We will create a few methods to leverage CRUD operations like insert, retrieve, and delete methods.
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();
}
}
Step 5: Create a Controller
Next, build CRUD REST API calls for the Student resource to fetch, insert, or delete resources in the MongoDB database.
The Spring @RestController annotation is used to create RESTful web services, and it combines both @Controller and @Responsebody annotations, making it easy to write handler methods.
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();
}
}
Step 6: Testing
Now, let's test one of the API calls in Postman to fetch data from the database as shown in the below image.
The below HTTP method returns all the student information in an array of JSON objects.
- Method: GET
Request URL: http://localhost:8080/student/getAllStudentsData
We have built a Spring Boot application leveraging the MongoDB database, and we have created CRUD operations such as creating, deleting, and fetching the data from the database, including different ways to fetch data. Spring Data MongoDB helps us to use the inbuilt methods for CRUD operations, which reduces the code complexity in the persistence layer.
Opinions expressed by DZone contributors are their own.
Comments