MongoTemplate批量更新(支持泛型)

MongoTemplate批量更新(支持泛型)

MongoTemplate所有批量操作中,批量添加是最简单的,直接使用mongoTemplate.insert()即可。

// MongoTemplate.class源码中insert方法有支持集合参数的重载函数,并且已经支持泛型
public <T> Collection<T> insert(Collection<? extends T> batchToSave, Class<?> entityClass)

其次,你可能想说批量删除,这时候就得借助批量操作对象BulkOperations,使用mongoTemplate.bulkOps()即可获取BulkOperations对象。

// BulkMode是一个枚举类,有BulkMode(有序)、UNORDERED(无序)两种枚举值
public BulkOperations bulkOps(BulkMode bulkMode, Class<?> entityClass)

接下来就要介绍一下怎么使用BulkOperations对象了,对于批量删除来说,使用如下api即可。

// Query对象一般指明_id字段的值即可,按id列表进行批量删除
BulkOperations remove(List<Query> var1);

完整的批量删除代码如下,支持泛型,可提供给所有实体对象调用。

@Test
public <T> void mongoRemove(List<T> idList, Class<?> entityClass) {
    List<Query> queryList = new LinkedList<>();
    for(T id : idList){
        queryList.add(Query.query(Criteria.where("_id").is(id)));
    }
    BulkOperations operations = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, entityClass);
    operations.remove(queryList);
    operations.execute();
}

那么批量更新呢,批量更新是否也那么简单呢,这就得谈谈批量更新的使用场景了。一般来说,批量更新以目标对象的_id作为查询字段,_id以外的所有字段作为更新字段。由此,批量更新如果要支持泛型的话,就有些困难了。
获取_id查询字段固然不困难,但其他字段因实体对象不同而不同,如果要提供给所有实体对象调用,那么需要兼容_id之外所有可能出现的字段。如果能做到兼容,使用BulkOperations对象的另一个api即可。

// Pair对象用于封装每对Query对象和Update对象,表示批量更新中每一次的执行的条件
BulkOperations upsert(List<Pair<Query, Update>> var1);
// 虽然updateMulti方法也能用于批量更新,但鉴于MongoTemplate.class中也有同名方法,一般使用upsert作批量更新
// updateMulti更多时候表示按照某一固定条件更新所有的符合文档,它的查询条件一般不用_id字段,因为_id字段唯一
BulkOperations updateMulti(List<Pair<Query, Update>> var1);

批量更新完整代码如下,支持泛型,可提供给所有实体对象调用。

@Test
public <T> void mongoUpdate(List<T> list, Class<?> entityClass) throws JsonProcessingException {
	// 把获取Pair<Query, Update>集合的任务交给工具类
    List<Pair<Query, Update>> pairList = MongoUtils.getPairList(list);
    BulkOperations operations = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, entityClass);
	operations.upsert(pairList);
	operations.execute();
}

MongoUtils类如下,使用了Jackson先把目标对象转换为JSON字符串,再把JSON字符串转换为Document对象,用Document对象来指定Update对象,以此来兼容所有可能出现的更新字段。

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.ObjectUtils;
import org.bson.Document;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.util.Pair;

import java.util.LinkedList;
import java.util.List;

public class MongoUtils {
    public static <T> List<Pair<Query, Update>> getPairList(List<T> list) throws JsonProcessingException {
        List<Pair<Query, Update>> pairList = new LinkedList<>();
        for (T t : list) {
        	// 循环获取Pair对象
            Pair<Query, Update> pair = getPair(t);
            pairList.add(pair);
        }
        return pairList;
    }

    private static <T> Pair<Query, Update> getPair(T t) throws JsonProcessingException {
        Query query = new Query();
        Update update = new Update();
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(t);
        Document document = objectMapper.readValue(json, Document.class);
        // 删除key为“_id”的键值对,同时返回value
        Object id = document.remove("_id");
        // 指定查询字段
        query.addCriteria(Criteria.where("_id").is(id));
        // 指定更新字段
		document.forEach(update::set);
		// 如果你不想更新目标对象为null的字段,使用下列forEach函数替代上一行代码
        /*document.forEach((key, value)->{
            if(ObjectUtils.isNotEmpty(value)){
                update.set(key, value);
            }
        });*/
        // 返回Pair对象
        return Pair.of(query, update);
    }
}
  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值