1. 程式人生 > 實用技巧 >MongoDB SpringBoot 批量更新

MongoDB SpringBoot 批量更新

  • 最近考慮對原有得Mongo 庫操作進行優化,老的邏輯會頻繁得操縱庫,而且還是單條得,效能擔憂啊,所以考慮將單條更新轉換成批量更新,話不多說,直接上程式碼.
  1. 新增一個供批量操作得物件
    @Data @NoArgsConstructor @AllArgsConstructor public class BatchUpdateOptions { private Query query; private Update update; private boolean upsert = true; private boolean multi = false; }

  2. 建立批量操作的Dao
    ``
    public class MongoBaseDao {

    /**

    • 批量更新
    • @param ordered 如果為true,一條語句更新失敗,剩下的語句將不再執。如果為false,一條語句更新失敗,剩下的將繼續執行。預設為true。
    • @return
      */
      public static int batchUpdate(MongoTemplate mongoTemplate, String collectionName, List options, boolean ordered) {
      return doBatchUpdate(mongoTemplate, collectionName, options, ordered);
      }

    private static int doBatchUpdate(MongoTemplate mongoTemplate, String collName, List options, boolean ordered) {
    try{
    Document command = new Document();
    command.put("update", collName);
    List 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;
    

    }
    }
    ``

  3. Test
    ``
    List userList = new ArrayList();
    User us = new User();
    us.setId(1);
    us.setName("張三");
    userList.add(us);

List 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);
4. 新增一個工具類
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;
}

}
``

  1. 注意事項
    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……
  2. 所以一定要使用 mongoConverter.convertToMongoType(obj) 來設定 update的的value值.