A Complete Guide to Integrating MongoDB with Spring Boot

    A Complete Guide to Integrating MongoDB with Spring Boot

    Learn how Spring Boot application works with MongoDB, create entities with proper annotations, Pagination and CRUD Operations.

    default profile

    Anuj Kumar Sharma

    September 13, 2025

    5 min read

    Welcome back! In our previous post, we got MongoDB up and running and learned essential commands. Now it's time to put that knowledge to work by integrating MongoDB with Spring Boot. If you've been following along, you already know how to query MongoDB from the shell - now let's see how Spring Data MongoDB makes this even more elegant in Java.

    This article is part of our comprehensive 4-part MongoDB with Spring Boot series.

    Part 1: Getting Started with MongoDB: Installation and Basic Commands

    Part 2 (Current): MongoDB with Spring Boot using Spring-Data-MongoDB

    Part 3: MongoDB Relationships in Spring Boot

    Part 4: Advanced MongoDB Queries: Mastering Criteria API and MongoTemplate

    Setting Up Your Spring Boot Project#

    First things first - let's create a Spring Boot project with MongoDB support. Head over to Spring Initializr or add these dependencies to your existing project:

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>

    Configure your MongoDB connection in application.yml:

    spring: data: mongodb: uri: mongodb://localhost:27017/ecommerce_db auto-index-creation: true

    That auto-index-creation property is important - it tells Spring to automatically create indexes based on your annotations. Remember those indexes we created manually in the last post? Spring can handle that for us now.

    Understanding MongoDB Annotations#

    Spring Data MongoDB provides powerful annotations that map Java objects to MongoDB documents. Let's explore the key ones you'll use constantly.

    The @Document Annotation#

    The @Document annotation marks a class as a MongoDB document. It's like @Entity in JPA, but for MongoDB:

    @Document(collection = "orders") public class Order { // fields here }

    This tells Spring that instances of this class should be stored in the "orders" collection. If you omit the collection name, Spring uses the class name in lowercase.

    The @Id Annotation#

    Every document needs a unique identifier. In MongoDB, this is typically an ObjectId, but Spring is flexible:

    @Id private String id;

    Spring automatically converts between MongoDB's ObjectId and Java's String. You can also use ObjectId directly if you prefer, but String is more convenient.

    Auditing with @CreatedDate and @LastModifiedDate#

    Want to track when documents are created and updated? Spring's auditing annotations have you covered:

    @CreatedDate private LocalDateTime createdAt; @LastModifiedDate private LocalDateTime updatedAt;

    Don't forget to enable auditing in your configuration:

    @Configuration @EnableMongoAuditing public class MongoConfig { // configuration here }

    The @Indexed Annotation#

    Remember creating indexes manually? With Spring, just annotate the field:

    @Indexed private String status; @Indexed(unique = true) private String email;

    Spring creates these indexes automatically when the application starts. You can verify this in the MongoDB shell:

    db.orders.getIndexes()

    Creating Your First Entity#

    Let's create our Order entity with all the bells and whistles:

    @Data @Builder @Document(collection = "orders") public class Order { @Id private String id; @CreatedDate private LocalDateTime createdAt; @LastModifiedDate private LocalDateTime updatedAt; private String status; private int quantity; private double totalPrice; }

    The @Data annotation from Lombok generates getters, setters, toString, equals, and hashCode methods. The @Builder annotation provides a fluent API for object creation - perfect for tests!

    Repository Pattern with Spring Data MongoDB#

    Here's where Spring Data truly shines. Instead of writing boilerplate CRUD code, you declare an interface:

    @Repository public interface OrderRepository extends MongoRepository<Order, String> { // That's it! CRUD operations are automatically available }

    Just by extending MongoRepository, you get:

    • save() for creating and updating
    • findById() for retrieving by ID
    • findAll() for getting all documents
    • delete() for removing documents
    • count() for counting documents
    • And much more!

    Custom Query Methods#

    Spring Data MongoDB can derive queries from method names:

    @Repository public interface OrderRepository extends MongoRepository<Order, String> { List<Order> findByStatus(String status); List<Order> findByTotalPriceGreaterThan(double price); List<Order> findByStatusAndQuantityLessThan(String status, int quantity); Optional<Order> findFirstByStatusOrderByCreatedAtDesc(String status); }

    Spring automatically generates the MongoDB queries based on these method names.

    Using @Query for Complex Queries#

    When method names get too long, use the @Query annotation:

    @Query("{ 'status': ?0, 'totalPrice': { $gte: ?1 } }") List<Order> findPendingOrdersAbovePrice(String status, double minPrice); @Query("{ 'createdAt': { $gte: ?0, $lt: ?1 } }") List<Order> findOrdersInDateRange(LocalDateTime start, LocalDateTime end);

    The ?0, ?1 are positional parameters. You can also use named parameters for clarity:

    @Query("{ 'status': :#{#status}, 'quantity': { $gt: :#{#minQty} } }") List<Order> findActiveOrders(@Param("status") String status, @Param("minQty") int minQuantity);

    CRUD Operations in Action#

    Let's write some tests to see our repository in action. This is where everything comes together:

    @SpringBootTest @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class OrderRepositoryTest { @Autowired private OrderRepository orderRepository; private static String orderId; @Test @Order(1) void createOrder() { Order order = Order.builder() .status("pending") .quantity(3) .totalPrice(299.97) .build(); Order saved = orderRepository.save(order); assertNotNull(saved.getId()); assertNotNull(saved.getCreatedAt()); assertEquals("pending", saved.getStatus()); orderId = saved.getId(); // Save for later tests } }

    Reading Documents#

    Finding documents is straightforward:

    @Test @Order(2) void findOrder() { Optional<Order> found = orderRepository.findById(orderId); assertTrue(found.isPresent()); assertEquals(299.97, found.get().getTotalPrice()); } @Test @Order(3) void findByStatus() { List<Order> pendingOrders = orderRepository.findByStatus("pending"); assertFalse(pendingOrders.isEmpty()); pendingOrders.forEach(order -> assertEquals("pending", order.getStatus()) ); }

    Updating Documents#

    Updates are as simple as saving an existing document:

    @Test @Order(4) void updateOrder() { Order order = orderRepository.findById(orderId).orElseThrow(); order.setStatus("processing"); order.setQuantity(5); Order updated = orderRepository.save(order); assertEquals("processing", updated.getStatus()); assertEquals(5, updated.getQuantity()); assertNotEquals(updated.getCreatedAt(), updated.getUpdatedAt()); }

    Deleting Documents#

    Removing documents is equally simple:

    @Test @Order(5) void deleteOrder() { orderRepository.deleteById(orderId); Optional<Order> deleted = orderRepository.findById(orderId); assertTrue(deleted.isEmpty()); }

    Pagination and Sorting#

    Real applications need pagination. Spring Data makes this elegant:

    @Test void paginationExample() { // Create some test data for (int i = 0; i < 20; i++) { orderRepository.save(Order.builder() .status("pending") .quantity(i) .totalPrice(i * 10.0) .build()); } // Paginate results Pageable pageable = PageRequest.of(0, 5, Sort.by("totalPrice").descending()); Page<Order> page = orderRepository.findAll(pageable); assertEquals(5, page.getContent().size()); assertEquals(20, page.getTotalElements()); assertEquals(4, page.getTotalPages()); }

    You can also add pagination to custom query methods:

    Page<Order> findByStatus(String status, Pageable pageable);

    What's Next?#

    We have now built a Spring Boot application with MongoDB, created entities with proper annotations, implemented CRUD operations, and even added pagination.

    But we're just scratching the surface. In my next post, we'll explore relationships in MongoDB. We will learn when to embed documents versus when to reference them, and how Spring Data MongoDB handles these relationships elegantly.

    Next Part here:

    Part 3: MongoDB Relationships in Spring Boot

    Want to Master Spring Boot and Land Your Dream Job?

    Struggling with coding interviews? Learn Data Structures & Algorithms (DSA) with our expert-led course. Build strong problem-solving skills, write optimized code, and crack top tech interviews with ease

    Learn more
    Spring Boot
    Mongo DB
    Spring Data MongoDB

    Subscribe to our newsletter

    Read articles from Coding Shuttle directly inside your inbox. Subscribe to the newsletter, and don't miss out.

    More articles