springboot + mongodb 切换数据库

springboot mongodb 切换数据库

​ spring boot + mongodb 切换数据库,注意这里是切换数据库而非多数据源。适用场景是在业务场景中根据参数切换 mongo 数据库名。

版本 :

  • springboot 2.3.4
  • mongodb-driver 4.0.5

maven 依赖 :

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

yml 配置 :

mongo:
  datasource:
    lists:  
      - uri: mongodb://ip:port/databaseName1
        database: databaseName1
      - uri: mongodb://ip:port/databaseName2
      	database: databaseName2

定义 mongo 属性类:

@Data
@Component
@ConfigurationProperties(prefix = "mongo.datasource")
public class MongoProperties {
    private List<MongoList> lists;
    @Data
    public static class MongoList {
        private String uri;
        private String database;
    }
}

重写 MongoTemplete 类 :

public class DynamicMongoTemplate extends MongoTemplate {
    
    public DynamicMongoTemplate(MongoDatabaseFactory mongoDbFactory, MongoConverter mongoConverter) {
        super(mongoDbFactory, mongoConverter);
    }
    
    @Override
    protected MongoDatabase doGetDatabase() {
        MongoDatabaseFactory factory = MongoContext.getMongoDatabaseFactory();
        return factory == null ? super.doGetDatabase() : factory.getMongoDatabase();
    }
}

定义 mongo context :

@Component
public class MongoContext {
    private static final Logger logger = LogManager.getLogger(MongoContext.class);
    private static final Map<String, MongoDatabaseFactory> databaseFactoryMap = new HashMap<>();
    private static final ThreadLocal<MongoDatabaseFactory> databaseThreadLocal = new ThreadLocal<>();
    private final MongoProperties mongoProperties;

    public MongoContext(MongoProperties mongoProperties) {
        this.mongoProperties = mongoProperties;
    }

    @PostConstruct
    public void afterPropertiesSet() {
        List<MongoProperties.MongoList> list = mongoProperties.getLists();
        MongoProperties.MongoList properties = new MongoProperties.MongoList();
        // 注: 此处 add 一个 mongo database 只是为了解决下面的 mongoTemplate() 方法
        // 中 iterator.hasNext() 为 false 时启动报错的问题,实际上 test database 并不存在
        properties.setDatabase("test");
        properties.setUri("mongodb://pi:port/test");
        if (!CollectionUtils.isEmpty(list)) {
            list.add(properties);
            list.forEach(mongo -> {
                databaseFactoryMap.put(mongo.getDatabase(),
                        new SimpleMongoClientDatabaseFactory(mongo.getUri()));
            });
        }
    }

    @Bean(name = "mongoTemplate")   // 此处 name 的定义需与具体 MongoTemplete 的注入处保持一致
    public DynamicMongoTemplate mongoTemplate() {
        Iterator<MongoDatabaseFactory> iterator = databaseFactoryMap.values().iterator();
        DbRefResolver refResolver = new DefaultDbRefResolver(iterator.next());
        MongoMappingContext mappingContext = new MongoMappingContext();
        // 设置驼峰命名转换
        mappingContext.setFieldNamingStrategy(new SnakeCaseFieldNamingStrategy());
        return new DynamicMongoTemplate(iterator.next(),
                new MappingMongoConverter(refResolver, mappingContext));
    }

    @Bean(name = "mongoDatabaseFactory")
    public MongoDatabaseFactory mongoDatabaseFactory() {
        Iterator<MongoDatabaseFactory> iterator = databaseFactoryMap.values().iterator();
        return iterator.next();
    }

    public static void setMongoDatabaseFactory(String databaseName) {
        logger.info("当前使用 mongo databaseName " + databaseName);
        databaseThreadLocal.set(databaseFactoryMap.get(databaseName));
    }

    public static MongoDatabaseFactory getMongoDatabaseFactory() {
        return databaseThreadLocal.get();
    }

    public static void removerMongoDatabaseFactory() {
        databaseThreadLocal.remove();
    }

}

使用示例 :

@Service
public class TestServiceImpl implements TestService {
    
    private final DynamicMongoTemplete mongoTemplete;
    // 以构造方法的方式注入
    public TestServiceImpl(DynamicMongoTemplete mongoTemplete) {
        this.mongoTemplete = mongoTemplete;
    }
    
    @Override
    public void test(String databaseName, String collectionName) {
        // 根据参数切换 database
        MongoContext.setMongoDatabaseFactory(databaseName);
        // 查询
        mongoTemplete.findAll(TestPo.class, collectionName);
    }
    
}

@XGLLHZ-《千千阙歌》.mp3-陈慧娴

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值