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.
0 Comments