This chapter will take you from installing MongoDB to integrating it into Spring Boot, explain the differences between JPA/ORM and document databases, cover relationships with @DBRef
, transactions, ResponseEntity
best-practices, Lombok, and connecting to Atlas. Like Chapter 1, I’ll keep explanations concrete and include copy-pasteable code.
Quick prerequisites & versions
- Java 17+ (LTS)
- Spring Boot 3.x (or newer)
- Maven (or Gradle)
- Basic command-line comfort and an editor/IDE (IntelliJ recommended)
1) Install MongoDB (Windows / Ubuntu / macOS) — practical steps
Use the MongoDB official docs for the most up-to-date platform-specific instructions. The official installation guides are authoritative and kept current.
macOS (Homebrew — simple)
- Install Homebrew (if you don’t have it).
- Tap the official MongoDB Homebrew repo and install the community server:
brew tap mongodb/brew
brew update
brew install mongodb-community
# start
brew services start mongodb/brew/mongodb-community
# stop
brew services stop mongodb/brew/mongodb-community
(If you prefer a specific version use mongodb-community@<version>
.) Official macOS install instructions: MongoDB docs & Homebrew tap.
Ubuntu / Debian (official repo)
A short/typical flow (replace <ubuntu-version>
and check the MongoDB docs for exact repo steps):
# 1. Import the public GPG key, add repo (follow official doc for exact repo string)
# 2. Update and install
sudo apt update
sudo apt install -y mongodb-org
# start
sudo systemctl start mongod
sudo systemctl enable mongod
Note: For current repo commands and guidance about versions (Ubuntu 22.04/24.04, etc.), follow MongoDB’s Ubuntu installation page.
Windows (MSI installer)
- Download the MongoDB Community MSI installer from MongoDB’s download page.
- Run the MSI, follow the wizard (choose “Complete” install and optionally install the MongoDB as a Windows Service).
- Start the
MongoDB
service (or runmongod
from command line if installed manually).
Official Windows MSI instructions are in the MongoDB docs.
2) Beginner’s walkthrough to MongoDB — key concepts (simplified)
-
Document — a JSON/BSON object (like a row but flexible). Example:
{ _id: ObjectId("..."), name: "Aisha", address: "Dhaka" }
. - Collection — group of documents (like a SQL table but schemaless).
- Database — container of collections.
-
BSON — binary encoding used by MongoDB (supports types like
ObjectId
, dates, binary). -
_id
— primary key, automatically generated if you don’t provide one. - Indexes — speed up queries (create where needed).
- Replica Set — multiple mongod instances that provide redundancy and allow multi-document transactions.
- Sharding — horizontal scaling for very large datasets.
MongoDB is a document database designed for ease of development and scalability. For canonical docs and conceptual reference see MongoDB manual.
MongoDB Shell (mongosh)
mongosh
is the modern MongoDB shell used for connecting to and interacting with MongoDB.
macOS (Homebrew)
brew install mongosh
mongosh
Ubuntu / Debian
sudo apt update
sudo apt install -y mongodb-mongosh
mongosh
Windows
- Download the mongosh MSI installer from MongoDB’s official download center.
- Install with the wizard and add
mongosh
to PATH if not auto-configured. - Run
mongosh
in Command Prompt or PowerShell.
Now you can test your connection:
mongosh "mongodb://localhost:27017"
3) Understanding ORM, JPA, Spring Data JPA — and how this differs from MongoDB
ORM & JPA (relational DBs):
- ORM maps Java objects ↔ relational tables.
-
JPA (Java Persistence API) is the standard API;
spring-data-jpa
is Spring’s convenient layer that implements repositories over JPA providers (Hibernate). Entities use@Entity
,@Table
, etc.
MongoDB (document DB) + Spring Data MongoDB:
- Documents instead of rows; no SQL, no RDBMS schema required.
- Spring Data provides a Mongo-specific module:
spring-boot-starter-data-mongodb
. You do not use JPA annotations for Mongo — use@Document
,@Id
, andMongoRepository
(orReactiveMongoRepository
for reactive). See Spring’s MongoDB getting-started guide.
Rule of thumb: Use JPA and ORM for SQL databases. For MongoDB use Spring Data MongoDB and document mapping annotations.
4) Integrate MongoDB with Spring Boot — step-by-step (classic example)
pom.xml (core deps)
<dependencies>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Data MongoDB -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- Optional: Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
The starter for Spring Data MongoDB is spring-boot-starter-data-mongodb
.
application.properties — local (embedded/installed mongod)
# local MongoDB
spring.data.mongodb.uri=mongodb://localhost:27017/studentsdb
# optional: server.port=8081
application.properties — MongoDB Atlas (example)
# Atlas connection (replace placeholders)
spring.data.mongodb.uri=mongodb+srv://<username>:<password>@cluster0.xxxxxx.mongodb.net/studentsdb?retryWrites=true&w=majority
Tip: If your password contains special characters, URL-encode it (spaces,
@
,:
etc.). Many Atlas connection problems come from unencoded credentials.
Domain (document) — Student.java
package com.example.studentapi.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection = "students")
public class Student {
@Id
private String id; // String is OK for simplicity (Mongo ObjectId as string)
private String name;
private String address;
private String phone;
// constructors / getters / setters (or use Lombok)
}
(You can use org.bson.types.ObjectId
for typed ids, but String is easiest for HTTP tests.)
Repository — StudentRepository.java
package com.example.studentapi.repository;
import com.example.studentapi.model.Student;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentRepository extends MongoRepository<Student, String> {
// findByName, etc., can be added as needed
}
Service & Controller (short example showing ResponseEntity)
See the ResponseEntity section below for details, but the structure is analogous to the JPA example in Chapter 1 — you inject the repository (via constructor) and expose endpoints in a @RestController
. For a full sample, see the next sections (ResponseEntity and cURL tests).
For a hands-on Spring guide with examples see Spring’s “Accessing Data with MongoDB” quickstart.
5) ResponseEntity in Spring Boot — proper HTTP status handling
ResponseEntity<T>
represents the full HTTP response (status, headers, body). Use it to send appropriate status codes from your controllers. Good practice:
-
201 Created
withLocation
header when creating resources. -
200 OK
for successful GETs/PUTs that return bodies. -
204 No Content
for successful DELETE with no body. -
404 Not Found
when a resource doesn't exist. -
400 Bad Request
for validation errors.
Controller examples
@PostMapping("/api/students")
public ResponseEntity<Student> create(@RequestBody Student s) {
Student created = service.create(s);
URI location = URI.create("/api/students/" + created.getId());
return ResponseEntity.created(location).body(created);
}
@GetMapping("/api/students/{id}")
public ResponseEntity<Student> getById(@PathVariable String id) {
return service.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@DeleteMapping("/api/students/{id}")
public ResponseEntity<Void> delete(@PathVariable String id) {
service.delete(id);
return ResponseEntity.noContent().build();
}
For deeper discussion and patterns, see resources on ResponseEntity
.
6) Mastering Project Lombok in Java — simplify boilerplate
Lombok removes repetitive getters/setters/constructors/builders. Example:
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.Builder;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Document(collection = "students")
public class Student {
@Id
private String id;
private String name;
private String address;
private String phone;
}
Quick tips:
- Enable annotation processing in IntelliJ: Settings → Build → Compiler → Annotation Processors (or the IDE-specific option).
- Be careful with Lombok + JPA lazy proxies: prefer
@Getter/@Setter
or avoid@EqualsAndHashCode
including associations — can cause stack traces or proxy issues. - Lombok is a build-time tool — keep it in
provided
/optional for some CI setups if desired.
7) Mastering MongoDB relationships in Spring Boot — @DBRef
vs embedding
Two main relationship patterns:
- Embedding — include related document inside parent (fast reads, denormalized).
- Example: embed contact info inside
Student
if it’s small and always read with student.
-
Referencing (
@DBRef
) — store a reference to another document (avoids duplication but requires extra lookup).
- Use
@DBRef
when you want separate collections & a document can be reused across many parents.
Example: Student
references a collection of Course
documents:
@Document
public class Course {
@Id
private String id;
private String title;
}
@Document
public class Student {
@Id
private String id;
private String name;
@DBRef(lazy = true)
private List<Course> courses;
}
Notes & trade-offs:
-
@DBRef
reduces duplication but adds extra fetches (and possible N+1 issues). - For query-heavy scenarios, embedding might be faster. Model according to access patterns.
- Spring Data MongoDB docs explain DBRef usage and caveats.
8) @Transactional
in Spring Boot — MongoDB transactions & @EnableTransactionManagement
Short summary: MongoDB added multi-document ACID transactions (since 4.0). To use them with Spring Data MongoDB you must run MongoDB as a replica set (Atlas clusters are replica sets by default). In Spring Boot you register a MongoTransactionManager
and annotate service methods with @Transactional
.
Minimal transaction config (Java)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.MongoTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class MongoConfig {
@Bean
MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
return new MongoTransactionManager(dbFactory);
}
}
Usage
@Service
public class StudentService {
private final StudentRepository repo;
public StudentService(StudentRepository repo) { this.repo = repo; }
@Transactional
public void createStudentAndLog(Student s, LogEntry log) {
repo.save(s);
// other repository operations — both operations commit or rollback together
}
}
Important caveat: Transactions require MongoDB to run in replica set mode (or Atlas) — a standalone mongod
without replica set won’t support multi-document transactions; you can convert a standalone to a single-node replica set for local testing if needed.
9) Connecting Spring Boot to MongoDB Atlas — step-by-step
- Sign up for MongoDB Atlas and create a free cluster (choose a cloud provider/region).
- Create a database user (username + password). Keep the password safe.
- Add your IP address to the Network Access (or use
0.0.0.0/0
temporarily for testing — not recommended for production). - In Atlas, click Connect → Connect your application to get the
mongodb+srv://...
connection string. Copy it and set it asspring.data.mongodb.uri
inapplication.properties
. - If your password has special characters, URL-encode it (e.g.,
%40
for@
). Common connection issues are caused by unencoded credentials.
Example application.properties
:
spring.data.mongodb.uri=mongodb+srv://myUser:my%40password@cluster0.xxxxxx.mongodb.net/studentsdb?retryWrites=true&w=majority
10) Quick debugging checklist & common pitfalls
- Cannot connect to Atlas — check IP whitelist and URL encoding in password. ([MongoDB][14])
- Transactions not working — ensure Mongo runs as a replica set or use Atlas (replica set). ([Home][15])
- Indexes missing — create indexes for query fields to avoid full-collection scans.
- Lombok problems in IDE — enable annotation processing.
-
@DBRef
performance — watch out for extra lookups; consider embedding where appropriate.
11) Quick copy-pasteable Student CRUD (Mongo version) — compact
Student.java (with Lombok)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Document(collection = "students")
public class Student {
@Id
private String id;
private String name;
private String address;
private String phone;
}
StudentRepository
public interface StudentRepository extends MongoRepository<Student, String> { }
StudentService
@Service
public class StudentService {
private final StudentRepository repo;
public StudentService(StudentRepository repo) { this.repo = repo; }
public Student create(Student s) { return repo.save(s); }
public List<Student> findAll() { return repo.findAll(); }
public Optional<Student> findById(String id) { return repo.findById(id); }
public Student update(String id, Student s) { s.setId(id); return repo.save(s); }
public void delete(String id) { repo.deleteById(id); }
}
StudentController (ResponseEntity usage)
@RestController
@RequestMapping("/api/students")
public class StudentController {
private final StudentService service;
public StudentController(StudentService service) { this.service = service; }
@PostMapping
public ResponseEntity<Student> create(@RequestBody Student s) {
Student created = service.create(s);
return ResponseEntity.created(URI.create("/api/students/" + created.getId())).body(created);
}
@GetMapping
public List<Student> all() { return service.findAll(); }
@GetMapping("/{id}")
public ResponseEntity<Student> getById(@PathVariable String id) {
return service.findById(id).map(ResponseEntity::ok).orElse(ResponseEntity.notFound().build());
}
@PutMapping("/{id}")
public ResponseEntity<Student> update(@PathVariable String id, @RequestBody Student s) {
return ResponseEntity.ok(service.update(id, s));
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable String id) {
service.delete(id);
return ResponseEntity.noContent().build();
}
}
Test with curl
as in Chapter 1 (replace localhost:8080
).
Conclusion
You’ve now set up MongoDB locally (with mongod
and mongosh
), integrated it into a Spring Boot project, and learned how it differs from JPA/ORM. We covered:
- Core MongoDB concepts (documents, collections,
_id
) - Spring Boot integration with
spring-boot-starter-data-mongodb
- Using
ResponseEntity
for proper HTTP status codes - Lombok to reduce boilerplate
- Relationships (
@DBRef
vs embedding) - Transactions in MongoDB with
MongoTransactionManager
- Connecting to MongoDB Atlas (cloud)
At this point, you can build a full CRUD REST API backed by MongoDB. From here, try:
- Experimenting with indexes for query optimization.
- Building relationships (e.g.,
Student
+Course
). - Deploying your Spring Boot + MongoDB app on a cloud platform (Heroku, AWS, etc.).
This chapter gave you the foundation — from installation to real-world REST APIs with Spring Boot + MongoDB. 🚀
Follow me on : Github Linkedin Threads Youtube Channel
Top comments (0)