- 最近考慮對原有得Mongo庫操作進行優化,老的邏輯會頻繁得操縱庫,而且還是單條得,性能擔憂啊,所以考慮將單條更新轉換成批量更新,話不多說,直接上代碼.
- 添加一個供批量操作得對象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BatchUpdateOptions {
private Query query;
private Update update;
private boolean upsert = true;
private boolean multi = false;
}
- 創建批量操作的Dao
public class MongoBaseDao {
/**
* 批量更新
* @param ordered 如果為true,一條語句更新失敗,剩下的語句將不再執。如果為false,一條語句更新失敗,剩下的將繼續執行。默認為true。
* @return
*/
public static int batchUpdate(MongoTemplate mongoTemplate, String collectionName, List<BatchUpdateOptions> options, boolean ordered) {
return doBatchUpdate(mongoTemplate, collectionName, options, ordered);
}
private static int doBatchUpdate(MongoTemplate mongoTemplate, String collName, List<BatchUpdateOptions> options, boolean ordered) {
try{
// BasicDBObject command = new BasicDBObject();
Document command = new Document();
command.put("update", collName);
List<Document> updateList = options.stream().map(option -> {
Document update = new Document();
update.put("q", option.getQuery().getQueryObject());
update.put("u", option.getUpdate().getUpdateObject());
update.put("upsert", option.isUpsert());
update.put("multi", option.isMulti());
return update;
}).collect(Collectors.toList());
command.put("updates", updateList);
command.put("ordered", ordered);
Document document = mongoTemplate.getDb().runCommand(command);
System.out.println("doc:"+document);
System.out.println("doc--n:"+document.get("n"));
System.out.println("doc--nModified:"+document.get("nModified"));
// n為符合Query查詢的記錄總數 因為是根據id進行的查詢, 原則上只要符合查詢的記錄數等於要更新的數量就代表成功
Object n = document.get("n");
System.out.println("doc--n--class:"+n.getClass());
if(n.getClass()==Integer.class){
return (Integer)n;
}
return Integer.parseInt(String.valueOf(n));
}catch (Exception e){
e.printStackTrace();
}
return 0;
}
- Test
List<User> userList = new ArrayList();
User us = new User();
us.setId(1);
us.setName("張三");
userList.add(us);
List<BatchUpdateOptions> collect = userList.stream().map(user -> {
Update update = BeanConversionValue.setUpdateValue(user,mongoConverter);
Query query = Query.query(Criteria.where("id").is(user.getId()).and("name").is("張三"));
return new BatchUpdateOptions(query, update, true, true);
}).collect(Collectors.toList());
int num = MongoBaseDao.batchUpdate(mongoTemplate, HotelConstant.EBK_INVENTORY_COLLECTION, collect, true);
System.out.println("更新數量是:{}",num);
- 添加一個工具類
public class BeanConversionValue {
public static Update setUpdateValue(Object op,MongoConverter mongoConverter){
Update update = new Update();
Field[] declaredFields = op.getClass().getDeclaredFields();
for(Field field: declaredFields){
String key = field.getName();// 獲取屬性名
String method = key.substring(0,1).toUpperCase()+key.substring(1);// 將屬性首字符大寫,方便get & set 方法
try {
Method setmethod = null;
if(StringUtils.equals(field.getType().getName(),"boolean")){
setmethod = op.getClass().getMethod("is"+method);// 獲取 get 方法
}else{
setmethod = op.getClass().getMethod("get"+method);// 獲取 get 方法
}
Object value = setmethod.invoke(op);// 通過 get 獲取值
System.out.println(key + "--" + value);
if(!StringUtils.equalsIgnoreCase("id",key)){
update.set(key, mongoConverter.convertToMongoType(value));
}
} catch (Exception e) {
e.printStackTrace();
Sentry.capture(e);
}
}
return update;
}
}
- 注意事項
update.set(key, mongoConverter.convertToMongoType(value));
這句代碼,如果不使用mongoConverter.convertToMongoType 進行轉換,部分類型MongoDB 無法直接轉換,在執行
Document document = mongoTemplate.getDb().runCommand(command);
就會報錯,報錯內容大致是:
org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class com.cn.local.list……
6. 所以一定要使用 mongoConverter.convertToMongoType(obj) 來設置 update的的value值.