要想在同一个springboot项目中使用多个数据源,最主要是每个数据源都有自己的mongoTemplate和MongoDbFactory。mongoTemplate和MongoDbFactory是负责对数据源进行交互的并管理链接的。
spring提供了一个注解@EnableMongoRepositories 用来注释在某些路径下的MongoRepositor实现类使用哪个MongoTemplate实例。当然如果我们是直接使用MongoTemplate操作,那么只需要使用于数据库对应的MongoTemplate即可。
代码结果如下:

首先实现两个config,实现对MongoTemplate和MongoDbFactory的配置
- mongoTemplate1和mongoDbFactory1:并使用@EnableMongoRepositories指定在"com.zhong.springdemo.mangodbdome.mongodb1"目录下的MongoRepositor使用这些配置。
java
@Configuration
//指定com.zhong.springdemo.mangodbdome.mongodb1路径下的MongoRepository使用 容器中的 mongoTemplate1实例
@EnableMongoRepositories(mongoTemplateRef = "mongoTemplate1",basePackages = {"com.zhong.springdemo.mangodbdome.mongodb1"})
public class MongoDbConfigure {
@Autowired
MongoDbFactoryProperties mongoDbFactoryProperties;
/**
* 自定义 mongoTemplate 实现多数据源配置
*/
@Bean("mongoTemplate1")
public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory1, MongoMappingContext context){
MappingMongoConverter mappingMongoConverter = mappingMongoConverter(mongoDbFactory1, context);
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory1, mappingMongoConverter);
return mongoTemplate;
}
/**
* 自定义mongo连接池
* @param properties 私有配置
* @return
*/
@Bean("mongoDbFactory1")
public MongoDbFactory mongoDbFactory(MongoDbProperties properties) {
//创建客户端参数
MongoClientOptions options = mongoClientOptions(properties);
//解析地址
List<ServerAddress> serverAddresses = new ArrayList<>();
for (String address : properties.getAddress().split(",")) {
String[] hostAndPort = address.split(":");
String host = hostAndPort[0];
Integer port = Integer.parseInt(hostAndPort[1]);
ServerAddress serverAddress = new ServerAddress(host, port);
serverAddresses.add(serverAddress);
}
//创建认证客户端
MongoCredential mongoCredential = MongoCredential.createScramSha1Credential(properties.getUsername(),
properties.getAuthenticationDatabase() != null ? properties.getAuthenticationDatabase() : properties.getDatabase(),
properties.getPassword().toCharArray());
MongoClient mongoClient = new MongoClient(serverAddresses.get(0), mongoCredential, options);
//集群模式
if (serverAddresses.size() > 1) {
mongoClient = new MongoClient(serverAddresses, mongoCredential, null);
}
/** 创建非认证客户端*/
//MongoClient mongoClient = new MongoClient(serverAddresses, mongoClientOptions);
return new SimpleMongoDbFactory(mongoClient, properties.getDatabase());
}
/**
* mongo客户端参数配置
* @return
*/
private MongoClientOptions mongoClientOptions(MongoDbProperties properties) {
MongoDbFactoryProperties factoryProperties = this.mongoDbFactoryProperties;
return MongoClientOptions.builder()
.connectTimeout(factoryProperties.getConnectionTimeoutMs())
.socketTimeout(factoryProperties.getReadTimeoutMs()).applicationName(factoryProperties.getApplicationName())
.heartbeatConnectTimeout(factoryProperties.getHeartbeatConnectionTimeoutMs())
.heartbeatSocketTimeout(factoryProperties.getHeartbeatReadTimeoutMs())
.heartbeatFrequency(factoryProperties.getHeartbeatFrequencyMs())
.minHeartbeatFrequency(factoryProperties.getMinHeartbeatFrequencyMs())
.maxConnectionIdleTime(factoryProperties.getConnectionMaxIdleTimeMs())
.maxConnectionLifeTime(factoryProperties.getConnectionMaxLifeTimeMs())
.maxWaitTime(factoryProperties.getPoolMaxWaitTimeMs())
.connectionsPerHost(factoryProperties.getConnectionsPerHost())
.threadsAllowedToBlockForConnectionMultiplier(
factoryProperties.getThreadsAllowedToBlockForConnectionMultiplier())
.minConnectionsPerHost(factoryProperties.getMinConnectionsPerHost()).build();
}
/**
* monogo 转换器
* @return
*/
private MappingMongoConverter mappingMongoConverter(MongoDbFactory mongoDbFactory1, MongoMappingContext context) {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory1);
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
//此处是去除插入数据库的 _class 字段
mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
return mappingConverter;
}
}
- mongoTemplate2和mongoDbFactory2:并使用@EnableMongoRepositories指定在"com.zhong.springdemo.mangodbdome.mongodb2"目录下的MongoRepositor使用这些配置。
java
@Configuration
//指定com.zhong.springdemo.mangodbdome.mongodb2路径下的MongoRepository使用 容器中的 mongoTemplate2实例
@EnableMongoRepositories(mongoTemplateRef = "mongoTemplate2",basePackages = {"com.zhong.springdemo.mangodbdome.mongodb2"})
public class MongoDbConfigure2 {
@Autowired
MongoDbFactoryProperties mongoDbFactoryProperties;
/**
* 自定义 mongoTemplate 实现多数据源配置
*/
@Bean("mongoTemplate2")
public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory2, MongoMappingContext context){
MappingMongoConverter mappingMongoConverter = mappingMongoConverter(mongoDbFactory2, context);
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory2, mappingMongoConverter);
return mongoTemplate;
}
/**
* 自定义mongo连接池
* @param properties 私有配置
* @return
*/
@Bean("mongoDbFactory2")
public MongoDbFactory mongoDbFactory2(MongoDbProperties2 properties) {
//创建客户端参数
MongoClientOptions options = mongoClientOptions(properties);
//解析地址
List<ServerAddress> serverAddresses = new ArrayList<>();
for (String address : properties.getAddress().split(",")) {
String[] hostAndPort = address.split(":");
String host = hostAndPort[0];
Integer port = Integer.parseInt(hostAndPort[1]);
ServerAddress serverAddress = new ServerAddress(host, port);
serverAddresses.add(serverAddress);
}
//创建认证客户端
MongoCredential mongoCredential = MongoCredential.createScramSha1Credential(properties.getUsername(),
properties.getAuthenticationDatabase() != null ? properties.getAuthenticationDatabase() : properties.getDatabase(),
properties.getPassword().toCharArray());
MongoClient mongoClient = new MongoClient(serverAddresses.get(0), mongoCredential, options);
//集群模式
if (serverAddresses.size() > 1) {
mongoClient = new MongoClient(serverAddresses, mongoCredential, null);
}
/** 创建非认证客户端*/
//MongoClient mongoClient = new MongoClient(serverAddresses, mongoClientOptions);
return new SimpleMongoDbFactory(mongoClient, properties.getDatabase());
}
/**
* mongo客户端参数配置
* @return
*/
private MongoClientOptions mongoClientOptions(MongoDbProperties2 properties) {
MongoDbFactoryProperties factoryProperties = this.mongoDbFactoryProperties;
return MongoClientOptions.builder()
.connectTimeout(factoryProperties.getConnectionTimeoutMs())
.socketTimeout(factoryProperties.getReadTimeoutMs()).applicationName(factoryProperties.getApplicationName())
.heartbeatConnectTimeout(factoryProperties.getHeartbeatConnectionTimeoutMs())
.heartbeatSocketTimeout(factoryProperties.getHeartbeatReadTimeoutMs())
.heartbeatFrequency(factoryProperties.getHeartbeatFrequencyMs())
.minHeartbeatFrequency(factoryProperties.getMinHeartbeatFrequencyMs())
.maxConnectionIdleTime(factoryProperties.getConnectionMaxIdleTimeMs())
.maxConnectionLifeTime(factoryProperties.getConnectionMaxLifeTimeMs())
.maxWaitTime(factoryProperties.getPoolMaxWaitTimeMs())
.connectionsPerHost(factoryProperties.getConnectionsPerHost())
.threadsAllowedToBlockForConnectionMultiplier(
factoryProperties.getThreadsAllowedToBlockForConnectionMultiplier())
.minConnectionsPerHost(factoryProperties.getMinConnectionsPerHost()).build();
}
/**
* monogo 转换器
* @return
*/
private MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context) {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
//此处是去除插入数据库的 _class 字段
mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
return mappingConverter;
}
}
- Repository实现
实现mongdb1下的repository---UserInfoTestRepository,UserInfoTestRepository使用的是mongoTemplate2和mongoDbFactory2
java
@Repository
public interface UserInfoTestRepository extends MongoRepository<UserInfoEntity, String> {
List<UserInfoEntity> findByUserNameLike(String username);
List<UserInfoEntity> findByUserName(String username);
}
实现mongdb2下的repository---UserInfRepository, UserInfRepository使用的是mongoTemplate1和mongoDbFactory1
java
@Repository
public interface UserInfoRepository extends MongoRepository<UserInfoEntity, String> {
List<UserInfoEntity> findByUserNameLike(String username);
List<UserInfoEntity> findByUserName(String username);
}
- 实现service
使用Repository实现的访问的service
java
@Service
public class UserInfoServiceImpl implements UserInfoService {
@Autowired
private UserInfoRepository userInfoRepository;
@Autowired
private UserInfoTestRepository userInfoTestRepository;
@Override
public List<UserInfoEntity> findByUserName(String userName){
return userInfoRepository.findByUserName(userName);
}
@Override
public int saveTestUser(List<UserInfoDto> userInfoDtos) {
List<UserInfoEntity> userInfoEntities = Lists.newArrayList();
for(UserInfoDto userInfoDto : userInfoDtos){
UserInfoEntity userInfoEntity = new UserInfoEntity();
BeanUtils.copyProperties(userInfoDto, userInfoEntity);
userInfoEntities.add(userInfoEntity);
}
userInfoTestRepository.saveAll(userInfoEntities);
return userInfoEntities.size();
}
@Override
public int saveUser(List<UserInfoDto> userInfoDtos) {
List<UserInfoEntity> userInfoEntities = Lists.newArrayList();
for(UserInfoDto userInfoDto : userInfoDtos){
UserInfoEntity userInfoEntity = new UserInfoEntity();
BeanUtils.copyProperties(userInfoDto, userInfoEntity);
userInfoEntities.add(userInfoEntity);
}
userInfoRepository.saveAll(userInfoEntities);
return userInfoEntities.size();
}
}
使用MongoTemplate实现的访问的service
java
@Service
public class UserInfoMongoTemplateServiceImpl implements UserInfoMongoTemplateService {
@Autowired
MongoTemplate mongoTemplate1;
@Autowired
MongoTemplate mongoTemplate2;
@Override
public List<UserInfoEntity> findByUserName(String userName){
Criteria criteria = Criteria.where("user_name").is(userName);
return mongoTemplate1.find(getQueryFilter(criteria), UserInfoEntity.class);
}
@Override
public int saveTestUser(List<UserInfoDto> userInfoDtos) {
List<UserInfoEntity> userInfoEntities = Lists.newArrayList();
for(UserInfoDto userInfoDto : userInfoDtos){
UserInfoEntity userInfoEntity = new UserInfoEntity();
BeanUtils.copyProperties(userInfoDto, userInfoEntity);
userInfoEntities.add(userInfoEntity);
}
mongoTemplate1.insert(userInfoEntities, UserInfoEntity.class);
return userInfoEntities.size();
}
@Override
public int saveUser(List<UserInfoDto> userInfoDtos) {
List<UserInfoEntity> userInfoEntities = Lists.newArrayList();
for(UserInfoDto userInfoDto : userInfoDtos){
UserInfoEntity userInfoEntity = new UserInfoEntity();
BeanUtils.copyProperties(userInfoDto, userInfoEntity);
userInfoEntities.add(userInfoEntity);
}
mongoTemplate2.insert(userInfoEntities, UserInfoEntity.class);
return userInfoEntities.size();
}
private Query getQueryFilter(Criteria criteria, String ...parms) {
criteria = criteria == null ? new Criteria() : criteria;
Query query = new Query();
query.addCriteria(criteria);
if(parms != null && parms.length > 0){
Field fields = query.fields();
for(String parm : parms){
fields.include(parm);
}
}
return query;
}
}
两个数据源信息配置properties.yaml:
bash
zhong:
#自定义的mongodb测试
data:
mongodb:
database: zhong-mongo
password: 123456
address: 127.0.0.1:27017
username: admin
authenticationDatabase: admin
mongodb2:
database: test-mongo
password: 123456
address: 127.0.0.1:27017
username: admin
authenticationDatabase: admin
测试类:
java
@Component
public class MongoStartTest implements CommandLineRunner {
@Autowired
UserInfoService userInfoService;
@Autowired
UserInfoMongoTemplateService userInfoMongoTemplateService;
@Override
public void run(String... args) throws Exception {
for(int i = 0; i < 25; i++){
UserInfoDto userInfoDto = new UserInfoDto();
userInfoDto.setUserId(UUID.randomUUID().toString().replace("-", ""));
userInfoDto.setUserName("用户名" + i);
userInfoDto.setAuthor("登录名" + i);
userInfoDto.setPwd("123456" + i);
userInfoDto.setCreateTime(new Date());
userInfoService.saveTestUser(Lists.newArrayList(userInfoDto));
userInfoService.saveUser(Lists.newArrayList(userInfoDto));
}
for(int i = 100; i < 125; i++){
UserInfoDto userInfoDto = new UserInfoDto();
userInfoDto.setUserId(UUID.randomUUID().toString().replace("-", ""));
userInfoDto.setUserName("用户名" + i);
userInfoDto.setAuthor("登录名" + i);
userInfoDto.setPwd("123456" + i);
userInfoDto.setCreateTime(new Date());
userInfoMongoTemplateService.saveTestUser(Lists.newArrayList(userInfoDto));
userInfoMongoTemplateService.saveUser(Lists.newArrayList(userInfoDto));
}
userInfoService.findByUserName("用户名");
userInfoMongoTemplateService.findByUserName("用户名");
}
}
结果如图:
数据的确被插入到不同的库中了

参考: