MongoDB SpringBoot 批量更新

  • 最近考虑对原有得Mongo库操作进行优化,老的逻辑会频繁得操纵库,而且还是单条得,性能担忧啊,所以考虑将单条更新转换成批量更新,话不多说,直接上代码.
  1. 添加一个供批量操作得对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BatchUpdateOptions {
    private Query query;
    private Update update;
    private boolean upsert = true;
    private boolean multi = false;
}
  1. 创建批量操作的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;
    }
  1. 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);
  1. 添加一个工具类
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……

6. 所以一定要使用 mongoConverter.convertToMongoType(obj) 来设置 update的的value值.

posted @ 2020-10-16 11:29  JoinLemon  阅读(1832)  评论(6编辑  收藏  举报