Modern applications, especially in a microservices architecture, often require interaction with multiple databases. This is particularly common with NoSQL databases like MongoDB, where different services might have their own dedicated databases. Spring Data MongoDB simplifies the management of multiple MongoDB datasources within your application. This article provides a comprehensive guide to achieve this.

1. Project Setup and Dependencies

Begin with a Spring Boot project and add the necessary MongoDB driver and Spring Data MongoDB dependencies in your pom.xml (Maven) or build.gradle (Gradle):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

2. Configuration with application.yml

Leverage Spring Boot’s externalized configuration by defining your database connection details in an application.yml file:

spring:
  data:
    mongodb:
      first:
        uri: mongodb://localhost:27017/firstdb
        # Add authentication details if needed
        # username: your-username
        # password: your-password
      second:
        uri: mongodb://localhost:27017/seconddb
        # Add authentication details if needed
        # username: your-username
        # password: your-password

This configuration sets up two distinct MongoDB connections, “first” and “second,” each specifying the uri with the database host, port, and database name. Include username and password if your databases require authentication.

3. Defining Multiple Configurations

Create separate configuration classes for each MongoDB database to manage connections effectively. In each class, define the connection details by referencing the application.yml properties and specify the packages to scan for Spring Data repositories.

@Configuration
@EnableMongoRepositories(basePackages = "com.example.repository.first", 
                       mongoTemplateRef = "firstMongoTemplate")
public class FirstMongoConfig {

    @Value("${spring.data.mongodb.first.uri}")
    private String firstMongoUri;

    @Bean
    @Primary
    public MongoTemplate firstMongoTemplate() throws Exception {
        return new MongoTemplate(firstMongoFactory());
    }

    @Bean
    @Primary
    public MongoDatabaseFactory firstMongoFactory() throws Exception {
        return new SimpleMongoClientDatabaseFactory(new ConnectionString(firstMongoUri));
    }
}

@Configuration
@EnableMongoRepositories(basePackages = "com.example.repository.second", 
                       mongoTemplateRef = "secondMongoTemplate")
public class SecondMongoConfig {

    @Value("${spring.data.mongodb.second.uri}")
    private String secondMongoUri;

    @Bean
    public MongoTemplate secondMongoTemplate() throws Exception {
        return new MongoTemplate(secondMongoFactory());
    }

    @Bean
    public MongoDatabaseFactory secondMongoFactory() throws Exception {
        return new SimpleMongoClientDatabaseFactory(new ConnectionString(secondMongoUri));
    }
}

In this example:

  • @EnableMongoRepositories: Specifies the base package for repositories using this configuration.
  • mongoTemplateRef: Links the repositories to the correct MongoTemplate.
  • Separate MongoTemplate and MongoDatabaseFactory beans are defined for each database.
  • @Primary annotation on the “first” configuration sets it as the default.
  • @Value injects the URI from application.yml into the respective variables.

4. Creating Repositories

Create separate packages for repositories interacting with each database, e.g., com.example.repository.first and com.example.repository.second. Define your repository interfaces within those packages:

package com.example.repository.first;

import com.example.model.FirstModel;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface FirstRepository extends MongoRepository<FirstModel, String> {
    // ... your repository methods ...
}

package com.example.repository.second;

import com.example.model.SecondModel;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface SecondRepository extends MongoRepository<SecondModel, String> {
    // ... your repository methods ...
}

5. Injecting and Using Repositories

Inject your repositories into your service classes and use them as needed:

@Service
public class MyService {

    @Autowired
    private FirstRepository firstRepository;

    @Autowired
    private SecondRepository secondRepository;

    // ... your service methods ...
}

Important Considerations:

  • Transactions: MongoDB supports multi-document transactions within a single database, but not across multiple databases.
  • Connection Pooling: Configure appropriate connection pooling for each datasource to optimize performance.
  • Error Handling: Implement robust error handling for connection failures and other issues.

By following these steps, you can effectively manage multiple MongoDB datasources in your Spring application. This approach provides flexibility and scalability, allowing you to design your application with clear separation of concerns and data access.


Discover more from GhostProgrammer - Jeff Miller

Subscribe to get the latest posts sent to your email.

By Jeffery Miller

I am known for being able to quickly decipher difficult problems to assist development teams in producing a solution. I have been called upon to be the Team Lead for multiple large-scale projects. I have a keen interest in learning new technologies, always ready for a new challenge.