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> var1);
// 虽然updateMulti方法也能用于批量更新,但鉴于MongoTemplate.class中也有同名方法,一般使用upsert作批量更新
// updateMulti更多时候表示按照某一固定条件更新所有的符合文档,它的查询条件一般不用_id字段,因为_id字段唯一
BulkOperations updateMulti(List> var1);
批量更新完整代码如下,支持泛型,可提供给所有实体对象调用。
@Test
public <T> void mongoUpdate(List<T> list, Class<?> entityClass) throws JsonProcessingException {
// 把获取Pair集合的任务交给工具类
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);
}
}