How to connect a Spring Boot application to MongoDB?
Connecting Spring Boot to MongoDB is a very common task for modern Java apps.

This guide walks you through everything you need: project setup (Maven/Gradle), configuration, domain mapping, repositories (Spring Data MongoDB), advanced options (MongoTemplate, transactions), local development with Docker, testing, troubleshooting, and security tips. I’ll include runnable code snippets so you can copy-paste and get started quickly.
What you'll learn
• Required dependencies (Maven & Gradle)
• application.properties / application.yml examples (local, auth, replica set)
• Domain classes and repositories using Spring Data MongoRepository
• Using MongoTemplate and custom queries
• Enabling and using transactions
• Running MongoDB locally with Docker (including a single-node replica set)
• Integration testing with embedded MongoDB (Flapdoodle)
• Common problems and fixes, plus security best practices
Prerequisites
• Java 11+ (or Java 8 if you must; modern Spring Boot prefers 11+)
• Maven or Gradle
• Spring Boot (2.5+ or 3.x — examples assume Spring Boot starters)
• MongoDB server (local, Docker, or managed cloud like Atlas)
1 — Add dependencies
Maven (pom.xml)
<dependencies>
<!-- Spring Boot starter for web (optional, if building REST API) -->
<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: embed MongoDB for tests -->
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Gradle (build.gradle.kts)
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
testImplementation("de.flapdoodle.embed:de.flapdoodle.embed.mongo")
}
2 — Configure connection (application.properties / application.yml)
You can put your connection string in application.properties or application.yml. It’s recommended to use environment variables for credentials in production.
Simple local (no auth) — application.properties
spring.data.mongodb.database=mydb
spring.data.mongodb.uri=mongodb://localhost:27017/mydb
Using credentials and options
spring.data.mongodb.uri=mongodb://user:password@localhost:27017/mydb?authSource=admin&retryWrites=true&w=majority
YAML version (application.yml)
spring:
data:
mongodb:
uri: mongodb://user:password@localhost:27017/mydb?authSource=admin&retryWrites=true&w=majority
Replica set (required for transactions)
spring.data.mongodb.uri=mongodb://user:password@mongo1:27017,mongo2:27017,mongo3:27017/mydb?replicaSet=rs0&retryWrites=true&w=majority
3 — Domain model & repository (Spring Data)
Example domain class
package com.example.demo.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import java.time.LocalDateTime;
@Document(collection = "products")
public class Product {
@Id
private String id; // stores MongoDB ObjectId as hex string
private String name;
private String description;
private double price;
private LocalDateTime createdAt;
// getters, setters, constructors...
}
Notes:
Use @Document(collection = "name") to map the collection.
@Id can be String or org.bson.types.ObjectId. Using String is convenient because Spring converts for you.
Repository interface
package com.example.demo.repo;
import com.example.demo.model.Product;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List;
public interface ProductRepository extends MongoRepository<Product, String> {
List<Product> findByNameContainingIgnoreCase(String nameFragment);
}
Spring Data generates implementation automatically. Use typical CRUD methods: save, findById, findAll, deleteById.
4 — Service and Controller (example REST CRUD)
Service (simple)
@Service
public class ProductService {
private final ProductRepository repo;
public ProductService(ProductRepository repo) { this.repo = repo; }
public Product create(Product p) {
p.setCreatedAt(LocalDateTime.now());
return repo.save(p);
}
public Optional<Product> getById(String id) { return repo.findById(id); }
public List<Product> search(String q) { return repo.findByNameContainingIgnoreCase(q); }
public void delete(String id) { repo.deleteById(id); }
}
Controller
@RestController
@RequestMapping("/api/products")
public class ProductController {
private final ProductService svc;
public ProductController(ProductService svc) { this.svc = svc; }
@PostMapping
public ResponseEntity<Product> create(@RequestBody Product p) {
return ResponseEntity.status(HttpStatus.CREATED).body(svc.create(p));
}
@GetMapping("/{id}")
public ResponseEntity<Product> get(@PathVariable String id) {
return svc.getById(id).map(ResponseEntity::ok).orElse(ResponseEntity.notFound().build());
}
@GetMapping("/search")
public List<Product> search(@RequestParam String q) { return svc.search(q); }
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable String id) {
svc.delete(id);
return ResponseEntity.noContent().build();
}
}
5 — Using MongoTemplate for custom queries
MongoRepository covers many use-cases; MongoTemplate is useful for complex queries or aggregations.
@Service
public class CustomProductService {
private final MongoTemplate mongoTemplate;
public CustomProductService(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; }
public List<Product> findExpensiveProducts(double minPrice) {
Query q = new Query(Criteria.where("price").gte(minPrice));
q.with(Sort.by(Sort.Direction.DESC, "price"));
return mongoTemplate.find(q, Product.class);
}
}
MongoTemplate also supports aggregation pipelines with Aggregation classes.
6 — Transactions with MongoDB
MongoDB supports multi-document transactions starting with 4.0, but they require a replica set (even single-node replica set). Spring provides MongoTransactionManager.
Spring config for transactions
@Configuration
@EnableTransactionManagement
public class MongoConfig {
@Bean
MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
return new MongoTransactionManager(dbFactory);
}
}
Using transactions
@Transactional
public void performMultipleOps() {
// multiple repository saves or template operations will be in same transaction
repo.save(entity1);
repo.save(entity2);
}
Remember: to use transactions locally, your Mongo instance must be a replica set. See Docker section below.
7 — Run MongoDB locally with Docker (single-node replica set for transactions)
A minimal docker-compose for a single-node replica set:
version: "3.8"
services:
mongo:
image: mongo:6 # or your preferred version
container_name: mongo
ports:
- "27017:27017"
command: ["mongod", "--replSet", "rs0", "--bind_ip_all"]
volumes:
- ./mongo-data:/data/db
Start:
docker-compose up -d
Initialize replica set:
# either use mongosh inside container
docker exec -it mongo mongosh --eval "rs.initiate()"
If you need auth, create an admin user:
docker exec -it mongo mongosh
> use admin
> db.createUser({user: "admin", pwd: "securepass", roles:["root"]})
Then use the URI with credentials:
mongodb://admin:securepass@localhost:27017/?authSource=admin&replicaSet=rs0
8 — Integration testing: Flapdoodle embedded Mongo
Add Flapdoodle dependency (already shown earlier). In tests, Spring Boot auto-config will connect to embedded Mongo when available.
Example JUnit 5 test:
@SpringBootTest
@AutoConfigureDataMongo
public class ProductRepositoryTests {
@Autowired
private ProductRepository repo;
@Test
void testSaveAndFind() {
Product p = new Product(null, "Test", "desc", 9.99, LocalDateTime.now());
repo.save(p);
assertFalse(repo.findById(p.getId()).isEmpty());
}
}
This is great for CI because it avoids requiring external MongoDB.
9 — Practical tips, gotchas & troubleshooting
Connection refused: check Mongo server is running and correct host/port. If running in Docker, confirm ports and network.
Authentication failed: ensure correct authSource (often admin) and that the user exists in that DB.
Replica set required for transactions: if transactions fail, verify rs.status() and that replicaSet option is set in URI.
SSL/TLS errors: add tls=true and proper certificates, or disable certificate validation only for dev (not recommended for prod).
ObjectId mapping: if using String for @Id, Spring maps it to/from ObjectId automatically. If you use ObjectId type, import org.bson.types.ObjectId.
Indexes: create indexes for frequently queried fields. You can annotate your model with @Indexed:
@Indexed(direction = IndexDirection.DESCENDING)
private LocalDateTime createdAt;
Performance: avoid unbounded queries (large pages). Use pagination with Pageable.
Document design: MongoDB favors denormalized documents for read performance. Embed sub-documents when they are accessed together.
10 — Security & production best practices
Do not hardcode credentials in application.properties. Use environment variables or secret managers.
spring.data.mongodb.uri=${MONGODB_URI}
Least privilege: create separate DB users with least privilege needed.
TLS: enable TLS for in-transit encryption.
IP whitelisting: only allow known IPs in cloud-managed MongoDB (Atlas).
Monitoring: enable monitoring/metrics (MongoDB Ops Manager, Atlas, or Prometheus exporters).
Backups: schedule periodic backups and test restores regularly.
11 — Quick checklist before you deploy
Connection string stored securely (env var / vault)
Proper user roles & authSource configured
Replica set configured if you require transactions
Indexes created for critical queries
Secrets rotated regularly
Monitoring and backups enabled
Example: full application.yml for production (env vars)
spring:
data:
mongodb:
uri: ${MONGODB_URI}
Where MONGODB_URI might be:
mongodb://appuser:secret@mongo1:27017,mongo2:27017/mydb?authSource=admin&replicaSet=rs0&retryWrites=true&w=majority
Spring Data MongoDB makes it very quick to get started: define your domain, repository, and start CRUD operations.
For complex operations, MongoTemplate and aggregation pipelines cover the gaps.
Always test locally (Docker or embedded Mongo) and validate replica set & auth configuration if you need transactions.
About the Creator
Article Pins
Happy learning!
Enjoyed the story? Support the Creator.
Subscribe for free to receive all their stories in your feed.
Comments
There are no comments for this story
Be the first to respond and start the conversation.