Spring Boot MongoDB CRUD Example

author-image   By Dhiraj,   06 July, 2019 12K

In this tutorial, we will learn to integrate MongoDB with a spring boot application and perform different CRUD operations through Spring Data MongoRepository as well as MongoTemplate with different examples and samples. The different CRUD operations such as Create, Read, Update and Delete will be first implemented through MongoRepository and the same operations will be again implemented in MongoTemplate to provide the implementation differences between both the approaches. Also, we will have the REST endpoints exposed to perform these operations. Hence, we are going to develop an end to end spring boot MongoDB example app to perform different CRUD operations.

In this tutorial, we will be developing the sample app with Spring Boot 2 i.e. 2.1.6.RELEASE and hence the MongoDB driver version will be 3+ i.e. 3.8.2

We will have two entities defined as Department and Employee with one to many relationships - one department can have multiple employees. We will not be using @DBRef to visualise relational mapping kind of mapping as it does not fits well in NoSQL paradigm. You can refer this article that provides a good reason for this. Hence, we will be using embedded relations. But our repository implementation will have a mechanism to fetch all the employees by department or fetch department by employee name.

Spring Boot MongoDB Project Setup

Let us configure our Spring Boot app to use MongoDB first.

Spring Boot MongoDB Maven Dependencies

First let us start with defining our dependencies. As we will be using Maven, below is our pom.xml.

pom.xml
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-mongodb</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

Project Stucture

Below is our project structure.

spring-boot-mongodb-project-strct

Spring Boot MongoDB Properties Configuration

With Mongo 3.0 Java driver, spring.data.mongodb.host and spring.data.mongodb.port are not supported. In such cases, spring.data.mongodb.uri should be used to provide all of the configuration. Hence, below is our configuration file with spring.data.mongodb.uri

application.properties
spring.data.mongodb.uri=mongodb://root:root@localhost:27017/test_db
logging.level.root=DEBUG

As per our configuration, Mongo DB is running locally at default port 27017. We are using test_db database with this example and root is the username/password to access the same. If your Mongo process is not started with mongod --auth, then it is not required to provide the username and password.

With this much configuration and spring-boot-starter-data-mongodb at the classpath, Spring creates an instance of MongoTemplate and available for autowiring.

If we want to customize our MongoTemplate default bean then we can go ahead with java configurations for the same.

MongoDB Model Implementation

As we discussed above, we have a one-many relationship between Department and Employee model, the Department.java definition will have a list of employees in it.

Department.java
@Document("Department")
public class Department {

    @Id
    private String id;

    @Indexed(name = "deptName")
    private String name;
    private String description;

    //@DBRef
    private List employees;
//getters and setters

Document identifies a domain object to be persisted to MongoDB.

@Id demarcates an identifier.

Employee.java
@Document("Employee")
public class Employee {

    @Id
    private String empId;
    private String name;
    private int age;
    private double salary;

//getters and setters

Spring Data MongoRepository Implementation

Spring Data includes repository support for MongoDB and the queries are constructed automatically, based on method names similar to JPARepository. The below implementation also shows an example to execute custom query in a MongoRepository using @Query annotation. We have used this query to find department of an employee by an employee name.

DepartmentRepository.java
@Repository
public interface DepartmentRepository extends MongoRepository {

    @Query(value = "{'employees.name': ?0}", fields = "{'employees' : 0}")
    Department findDepartmentByEmployeeName(String empName);

    List findDepartmentByName(String name);
}

Using fields, we can tell the driver about the fields that we are intrested in the result set.

Spring Boot MongoDB API implementation

Now, let us define our API implementation in a spring controller class that performs the CRUD operation. It will make use of predefined method names in MongoRepository to perform these operations. While implementing our Mongotemplate, we will be defining these implementation again with Query interface.

Create Operation

Create operation is a POST request and takes Department model object as a parameter and uses repository pre-defined save() method to persist it to Mongo DB. It returns the saved instance and hence it will have the unique id in it.

@PostMapping
public Department createDept(@RequestBody Department department) {
	departmentRepository.save(department);
	return department;
}

Below is the equivalent implementation using MongoTemplate for Create operation.

public Department save(Department department) {
        mongoTemplate.save(department);
        return department;
    }

Read Operation

Read operation is a GET request and uses findAll() defined in MongoRepository that returns all the documents of a collection.

@GetMapping
public List listDepts(){
    return departmentRepository.findAll();
 }

Below is the equivalent implementation using MongoTemplate for Read operation.

public List findAll() {
     return mongoTemplate.findAll(Department.class);
}

Update Operation

Update operation uses PUT request and accepts deptId as a path variable and calls the same save(). In this case, since the id is present in the model object, it will get updated in the DB.

@PutMapping("/{deptId}")
    public Department updateDept(@RequestBody Department department, @PathVariable String deptId) {
        department.setId(deptId);
        departmentRepository.save(department);
        return department;
    }

Below is the equivalent implementation using MongoTemplate for update operation.

public Department update(Department department){
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(department.getId()));
        Update update = new Update();
        update.set("name", department.getName());
        update.set("description", department.getDescription());
        return mongoTemplate.findAndModify(query, update, Department.class);
    }

Delete Operation

Delete operation uses delete request. Below is the controller implementation.

@DeleteMapping("/{deptId}")
    public String deleteDept(@PathVariable String deptId) {
        departmentRepository.deleteById(deptId);
        return deptId;
    }

Below is the equivalent implementation using MongoTemplate for delete operation.

public void deleteById(String deptId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(deptId));
        mongoTemplate.remove(query, Department.class);
    }

Get Operation to Fetch Department By Name

It lists all the departments by name and show cases the usage of MongoRepository to query by attribute name of a model class.

@GetMapping("/{deptName}")
    public List findDeptByName(@PathVariable String deptName) {
        return departmentRepository.findDepartmentByName(deptName);
    }

Below is the equivalent implementation using MongoTemplate.

public List findDepartmentByName(String deptName){
        Query query = new Query();
        query.addCriteria(Criteria.where("name").is(deptName));
        return mongoTemplate.find(query, Department.class);
    }

Embedded Elements Operations

It fetches parent elements by an attribute of child element. This basically shows ways to query for embedded elements in MongoDB. As implemented above, this specific implementation executes custom query in our DepartmentRepository.java

@GetMapping("{name}/emp")
    public Department listDept(@PathVariable String name){
        return departmentRepository.findDepartmentByEmployeeName(name);
    }
DeptRepository.java
@Repository
public class DeptRepository {

    @Autowired
    private MongoTemplate mongoTemplate;

    public List findAll() {
        return mongoTemplate.findAll(Department.class);
    }

    public Department save(Department department) {
        mongoTemplate.save(department);
        return department;
    }

    public Department update(Department department){
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(department.getId()));
        Update update = new Update();
        update.set("name", department.getName());
        update.set("description", department.getDescription());
        return mongoTemplate.findAndModify(query, update, Department.class);
    }

    public List findDepartmentByName(String deptName){
        Query query = new Query();
        query.addCriteria(Criteria.where("name").is(deptName));
        return mongoTemplate.find(query, Department.class);
    }

    public void deleteById(String deptId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(deptId));
        mongoTemplate.remove(query, Department.class);
    }
}

Testing Spring Boot MongoDB App

Now, our implementation is ready for testing. Let us start our SpringBootMongoApplication.java as a java application and hit our endpoints.

Create Operation Test

spring-boot-mongodb-post-request POST Request Payload
{
	"name":"Devglan",
	"description": "devglan",
	"employees":[
		{
		"empId":"CET02",
 		"age":23,
		"salary":542452
		}
		
	]
}

Fetch Department By Emp Name

spring-boot-mongodb-get-request

Conclusion

In this tutorial, we learnt about creating a spring boot app with MongoDB and exposed some REST endpoints for different CRUD operations. We integrated MongoRepository and MongoTemplate too. To add security in this application, you can follow this article.

If You Appreciate This, You Can Consider:

  • Like us at: Facebook or follow us at Twitter
  • Share this article on social media or with your teammates.
  • We are thankful for your never ending support.

About The Author

author-image

I am an energetic professional who enjoys the challenges involved in working with people and resolving real-time problems. Technical expertise in building highly scalable, distributed and self-healing cloud applications. Technical Skills: Java/J2EE, Spring Framework, Hibernate, Angular, Reactive Programming, Microservices, Rest APIs, Kafka, ELK, etc.

Further Reading on Spring Boot

1 Spring Data Mongodb Queries

2 Spring Boot Security Rest Basic Authentication

3 Hibernate Criteria Tutorial

4 Spring Boot Multiple Database Configuration

5 Spring Boot Apache Kafka

6 Jwt Role Based Authorization