📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.
🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (176K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
When we're using MongoDB as the database for a Spring Boot application, we can't use @GeneratedValue annotation in our models as it's not available. Hence we need a method to produce the same effect as we'll have if we're using JPA and an SQL database.
Related tutorial - Spring Boot MongoDB CRUD Example Tutorial
Learn complete spring boot at https://www.javaguides.net/p/spring-boot-tutorial.htmlThe general solution to this problem is simple. We'll create a collection (table) that'll store the generated sequence for other collections. During the creation of a new record, we'll use it to fetch the next value.
Define Maven Dependencies
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath />
<!-- lookup parent from repository -->
</parent>
<groupId>net.springboot.javaguides</groupId>
<artifactId>springboot-mongodb-crud-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-thymeleaf-web-app</name>
<description>Demo project for Spring Boot + Mongo DB CRUD Example
</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Collections
package net.guides.springboot.crud.model; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "database_sequences") public class DatabaseSequence { @Id private String id; private long seq; public DatabaseSequence() {} public String getId() { return id; } public void setId(String id) { this.id = id; } public long getSeq() { return seq; } public void setSeq(long seq) { this.seq = seq; } }
package net.guides.springboot.crud.model; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Transient; import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "Employee") public class Employee { @Transient public static final String SEQUENCE_NAME = "users_sequence"; @Id private long id; @NotBlank @Size(max = 100) @Indexed(unique = true) private String firstName; private String lastName; @NotBlank @Size(max = 100) @Indexed(unique = true) private String emailId; public Employee() { } public Employee(String firstName, String lastName, String emailId) { this.firstName = firstName; this.lastName = lastName; this.emailId = emailId; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmailId() { return emailId; } public void setEmailId(String emailId) { this.emailId = emailId; } @Override public String toString() { return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", emailId=" + emailId + "]"; } }
SequenceGeneratorService - Auto-Generate Sequence
package net.guides.springboot.crud.service;
import static org.springframework.data.mongodb.core.FindAndModifyOptions.options;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;
import java.util.Objects;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import net.guides.springboot.crud.model.DatabaseSequence;
@Service
public class SequenceGeneratorService {
private MongoOperations mongoOperations;
@Autowired
public SequenceGeneratorService(MongoOperations mongoOperations) {
this.mongoOperations = mongoOperations;
}
public long generateSequence(String seqName) {
DatabaseSequence counter = mongoOperations.findAndModify(query(where("_id").is(seqName)),
new Update().inc("seq",1), options().returnNew(true).upsert(true),
DatabaseSequence.class);
return !Objects.isNull(counter) ? counter.getSeq() : 1;
}
}
package net.guides.springboot.crud.service;
import static org.springframework.data.mongodb.core.FindAndModifyOptions.options;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;
import java.util.Objects;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import net.guides.springboot.crud.model.DatabaseSequence;
@Service
public class SequenceGeneratorService {
private MongoOperations mongoOperations;
@Autowired
public SequenceGeneratorService(MongoOperations mongoOperations) {
this.mongoOperations = mongoOperations;
}
public long generateSequence(String seqName) {
DatabaseSequence counter = mongoOperations.findAndModify(query(where("_id").is(seqName)),
new Update().inc("seq",1), options().returnNew(true).upsert(true),
DatabaseSequence.class);
return !Objects.isNull(counter) ? counter.getSeq() : 1;
}
}
Set Auto-Generated Field
Now, we can use the generateSequence() while creating a new record:@PostMapping("/employees") public Employee createEmployee(@Valid @RequestBody Employee employee) { employee.setId(sequenceGeneratorService.generateSequence(Employee.SEQUENCE_NAME)); return employeeRepository.save(employee); }Now, every time we save a new Employee, the id will be set automatically.
Comments
Post a Comment
Leave Comment