基础的东西不谈,先说思路。
我们跟踪源码可以发现每次查询时都会在MongoTemplate
中去获取MongoDatabase
实例,大概是这样:
FindIterableiterable = collectionCallback .doInCollection(getAndPrepareCollection(getDb(), collectionName));复制代码
其中getDb()是由工厂类MongoDbFactory
实现的。那么很简单了,我们只需要写一个自己的MongoDbFactory
配置进来,来实现“默认是当前月库,也可以手动选择月库”的效果。
上代码,首先是MongoDbFactory
:
/** * 继承 { @link SimpleMongoDbFactory },重写{ @code getDB}方法,添加月库实现 * * @author fonlin * @date 2018/6/28 */public class MonthlyMongoDbFactory extends SimpleMongoDbFactory { /** * 没有月库后缀的数据库名 */ private String databaseName; public MonthlyMongoDbFactory(MongoClientURI uri) { super(uri); } public MonthlyMongoDbFactory(MongoClient mongoClient, String databaseName) { super(mongoClient, databaseName); this.databaseName = databaseName; } public MongoDatabase getDb() throws DataAccessException { //获取当前ThreadLocal中的month String month = MonthSelector.getAndRemove(); //如果没有,则设置当前月 if (StringUtils.isEmpty(month)) { month = LocalDateTime.now().format(DateTimeFormatter.ofPattern(Constants.MONTH_PATTERN)); } return getDbByMonth(month); } private MongoDatabase getDbByMonth(String month) throws DataAccessException { Assert.hasText(month, "month must not be empty."); //拼出test_201806 String name = this.databaseName + "_" + month; //调用父类 return super.getDb(name); }}复制代码
很简单,继承默认实现SimpleMongoDbFactory
,重写getDb()方法加入我们自己的逻辑,最终还是调用父类的getDb(String dbName)方法。注意MonthSelector
,这是利用ThreadLocal
实现的手动选择月份策略,用法大概就是这样子:
MonthSelector.set("201805");Listusers = userDao.findAll();复制代码
这里把MonthSelector
粗略代码贴一下,不太懂的朋友们要去看下ThreadLocal
的。
/** * @author fonlin * @date 2018/6/28 */public class MonthSelector { private static final ThreadLocalLOCAL_MONTH = new ThreadLocal<>(); public static String getAndRemove() { String month = LOCAL_MONTH.get(); LOCAL_MONTH.remove(); return month; } public static void set(String month) { Assert.notNull(month, "month must not be null"); LOCAL_MONTH.set(month); } public static String get() { return LOCAL_MONTH.get(); }}复制代码
最后是springboot整合mongodb的java config:
@Configuration//必须要禁用spring boot的自动配置@EnableAutoConfiguration(exclude={MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})@EnableConfigurationProperties(MongoProperties.class)//激活@Repository注解,并且设置dao扫描包@EnableMongoRepositories(basePackages = "com.fonlin.cloudmanager.dao.mongodb")public class MongoDbConfig extends AbstractMongoConfiguration { private final MongoProperties properties; private final MongoClientFactory factory; private final MongoClientOptions options; private MongoClient mongo; public MongoDbConfig(MongoProperties properties, ObjectProvideroptions, Environment environment) { this.properties = properties; this.options = options.getIfAvailable(); this.factory = new MongoClientFactory(properties, environment); } @Bean public MongoDbFactory mongoDbFactory() { //这里new我们自己的MongoDbFactory即可 return new MonthlyMongoDbFactory(mongoClient(), getDatabaseName()); } @PreDestroy public void close() { if (this.mongo != null) { this.mongo.close(); } } @Override public MongoClient mongoClient() { this.mongo = this.factory.createMongoClient(this.options); return this.mongo; } @Override protected String getDatabaseName() { return this.properties.getDatabase(); }}复制代码
到此配置就结束了,使用的话就像jpa
Repository
一样使用即可。