Configuring mongodb multiple data sources with springboot

Time:2020-12-3

Configuring mongodb multiple data sources with springboot

1. Project construction

Add POM file

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

2. In application.properties Add configuration in

##start mongodb for basic
#----------------------------------------------
basic.spring.data.mongodb.host=localhost
basic.spring.data.mongodb.port=27016
basic.spring.data.mongodb.username=auto_compute
basic.spring.data.mongodb.password=vqOqSZRs
basic.spring.data.mongodb.database=auto_compute
#----------------------------------------------
##end mongodb for spirit
##start mongodb for auth
#----------------------------------------------
auth.spring.data.mongodb.host=localhost
auth.spring.data.mongodb.port=27016
auth.spring.data.mongodb.username=datacenter
auth.spring.data.mongodb.password=Bds6NadsfafGlV
auth.spring.data.mongodb.database=datacenter
#----------------------------------------------
##end mongodb for spirit

3. Configure the appropriate data source

Use mongotemplate to carry out Mongo related operations and write a basic abstract class

import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;

import java.util.ArrayList;
import java.util.List;

@Getter
@Setter
public abstract class AbstractMongoConfigure {

    private String host;
    private int port;
    private String username;
    private String password;
    private String database;


    public MongoDbFactory mongoDbFactory() throws Exception {
        /*//No authentication initialization method
        return new SimpleMongoDbFactory(new MongoClient(host, port), database);*/

        //Initialization method with authentication
        ServerAddress serverAddress = new ServerAddress(host, port);
        List<MongoCredential> mongoCredentialList = new ArrayList<>();
        MongoCredential mongoCredential = MongoCredential.createCredential(username, database, password.toCharArray());
        mongoCredentialList.add(mongoCredential);
        return new SimpleMongoDbFactory(new MongoClient(serverAddress, mongoCredentialList), database);
    }

    abstract public MongoTemplate getMongoTemplate() throws Exception;
}

Data source loading needs to inherit abstractmongoconfigure abstract class. As many data sources as there are, you need to create as many new data source loading classes

3.1. The first data source

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

@Configuration
@EnableMongoRepositories(basePackages = {"com.tcl.dc.autodata.dao.base"}, mongoTemplateRef = "mongoTemplate")
@ConfigurationProperties(prefix = "basic.spring.data.mongodb")
public class BasicMongoConfig extends AbstractMongoConfigure {

    @Primary
    @Bean(name = "mongoTemplate")
    @Override
    public MongoTemplate getMongoTemplate() throws Exception {
        return new MongoTemplate(mongoDbFactory());
    }
}

The value of basepackages is used for the corresponding base package, and prefix is application.properties Configuration values in

3.2. Second data source

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

@Configuration
@EnableMongoRepositories(basePackages = {"com.tcl.dc.autodata.dao.auth"}, mongoTemplateRef = "authMongoTemplate")
@ConfigurationProperties(prefix = "auth.spring.data.mongodb")
public class AuthMongoConfig extends AbstractMongoConfigure {

    @Bean(name = "authMongoTemplate")
    @Override
    public MongoTemplate getMongoTemplate() throws Exception {
        return new MongoTemplate(mongoDbFactory());
    }
}

4. Attention

1. One bean in multiple data sources needs to be set to mongotemplate, and the @ primary annotation must be added, otherwise webmvc ConfigurationSupport.class We will report an error later. We can’t find mongotemplate

2. Spring boot will automatically inject mongotemplate, which conflicts with multiple data sources configured by us. To prevent default injection, you need to exclude classes that are automatically injected. Boot class in spring boot Applocation.java Add exclusion class annotation

@SpringBootApplication(exclude = {
        MongoAutoConfiguration.class,
        MongoDataAutoConfiguration.class})

5. Use multiple data sources

When used, it can be injected directly

@Autowired
@Qualifier(value = "mongoTemplate")
MongoTemplate mongoTemplate;

@Autowired
@Qualifier(value = "authMongoTemplate")
MongoTemplate authMongoTemplate;

6. Possible problems

1、’com.mongodb.MongoClient’ that could not be found

Detailed errors are as follows:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method mongoDbFactory in org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration required a bean of type 'com.mongodb.MongoClient' that could not be found.
    - Bean method 'mongo' not loaded because auto-configuration 'MongoAutoConfiguration' was excluded


Action:

Consider revisiting the conditions above or defining a bean of type 'com.mongodb.MongoClient' in your configuration.

Cause: after rewriting mongoclient and so on, the original automatic injection lacks beans

Solution: it mainly depends on which auto injected class references the default mongoclient and excludes it. For example:

@SpringBootApplication(exclude = {
        MongoAutoConfiguration.class,
        MongoDataAutoConfiguration.class})
2、more than one ‘primary’ bean found among candidates

Detailed errors are as follows:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sampleController': Unsatisfied dependency expressed through field 'mongoTemplate'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.data.mongodb.core.MongoTemplate' available: more than one 'primary' bean found among candidates: [logMongoTemplate, userMongoTemplate, mongoTemplate]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at com.biologic.Applocation.main(Applocation.java:18) [classes/:na]
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.data.mongodb.core.MongoTemplate' available: more than one 'primary' bean found among candidates: [logMongoTemplate, userMongoTemplate, mongoTemplate]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.determinePrimaryCandidate(DefaultListableBeanFactory.java:1365) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.determineAutowireCandidate(DefaultListableBeanFactory.java:1326) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1113) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]

Reason: spring boot will automatically inject a default mongotemplate or set multiple @ primary data sources

Solution: exclude the classes automatically injected by spring boot. Only one mongotemplate that is automatically overridden needs to be set to @ primary