基礎的東西不談,先說思路。
我們跟蹤原始碼可以發現每次查詢時都會在MongoTemplate
中去獲取MongoDatabase
例項,大概是這樣:
FindIterable<Document> iterable = 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");
List<User> users = userDao.findAll();
複製程式碼
這裡把MonthSelector
粗略程式碼貼一下,不太懂的朋友們要去看下ThreadLocal
的原理。
/**
* @author fonlin
* @date 2018/6/28
*/
public class MonthSelector {
private static final ThreadLocal<String> LOCAL_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,
ObjectProvider<MongoClientOptions> options, 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
一樣使用即可。