spring-data-mongodb之批量更新操作

用过mongodb的同学想必都知道,以java驱动的语法举例,插入式有insert方法的,支持插入集合,也就是批量插入。

@Override
	public  void insertAllDemo(List<DemoEntity> list) {
    	mongoTemplate.insertAll(list);
    }

但是update方法却只能执行一个更新条件,参数不支持传集合进去,也就意味着是不知道批量更新的。

当然原生的语法是支持的,只是驱动没有封装而已,官方文档也是推荐用db.runCommand()来实现的。

下面的语法中我们可以看到updates是个数组,可以执行多条更新语句,但是我们一般是在项目中使用,如果封装这个方法就行批量插入一样,今天我们就用spring-data-mongodb来做下封装。

首先定义一个封装更新参数的类

public class BathUpdateOptions {
    private Query query;
    private Update update;
    private boolean upsert = false;
    private boolean multi = false;
}

然后我们封装一个更新的方法,参数不同,重载多个


public static int bathUpdate(MongoTemplate mongoTemplate, String collName, 
         List<BathUpdateOptions> options, boolean ordered) {
        return doBathUpdate(mongoTemplate.getCollection(collName), collName, options, ordered);
    }
    
    public static int bathUpdate(DBCollection dbCollection, String collName, 
         List<BathUpdateOptions> options, boolean ordered) {
        return doBathUpdate(dbCollection, collName, options, ordered);
    }
    
    public static int bathUpdate(MongoTemplate mongoTemplate, Class<?> entityClass, 
        List<BathUpdateOptions> options, boolean ordered) {
        String collectionName = determineCollectionName(entityClass);
        return doBathUpdate(mongoTemplate.getCollection(collectionName), 
                collectionName, options, ordered);
    }
    
    public static int bathUpdate(DBCollection dbCollection, Class<?> entityClass, 
         List<BathUpdateOptions> options, boolean ordered) {
        return doBathUpdate(dbCollection, 
            determineCollectionName(entityClass), options, ordered);
    }
    
    
    public static int bathUpdate(MongoTemplate mongoTemplate, String collName,     
         List<BathUpdateOptions> options) {
        return doBathUpdate(mongoTemplate.getCollection(collName), collName, options, true);
    }
    
    public static int bathUpdate(DBCollection dbCollection, String collName, 
         List<BathUpdateOptions> options) {
        return doBathUpdate(dbCollection, collName, options, true);
    }
    
    public static int bathUpdate(MongoTemplate mongoTemplate, Class<?> entityClass, 
        List<BathUpdateOptions> options) {
        String collectionName = determineCollectionName(entityClass);
        return doBathUpdate(mongoTemplate.getCollection(collectionName), 
             collectionName, options, true);
    }
    
    public static int bathUpdate(DBCollection dbCollection, Class<?> entityClass,      
             List<BathUpdateOptions> options) {
        return doBathUpdate(dbCollection,
               determineCollectionName(entityClass), options, true);
    }
    
    
    private static int doBathUpdate(DBCollection dbCollection, String collName,         
                       List<BathUpdateOptions> options, boolean ordered) {
        DBObject command = new BasicDBObject();
        command.put("update", collName);
        List<BasicDBObject> updateList = new ArrayList<BasicDBObject>();
        for (BathUpdateOptions option : options) {
            BasicDBObject update = new BasicDBObject();
            update.put("q", option.getQuery().getQueryObject());
            update.put("u", option.getUpdate().getUpdateObject());
            update.put("upsert", option.isUpsert());
            update.put("multi", option.isMulti());
            updateList.add(update);
        }
        command.put("updates", updateList);
        command.put("ordered", ordered);
        CommandResult commandResult = dbCollection.getDB().command(command);
        return Integer.parseInt(commandResult.get("n").toString());
    }
    
    private static String determineCollectionName(Class<?> entityClass) {
        if (entityClass == null) {
            throw new InvalidDataAccessApiUsageException(
                    "No class parameter provided, entity collection can't be determined!");
        }
        String collName = entityClass.getSimpleName();
        if(entityClass.isAnnotationPresent(Document.class)) {
            Document document = entityClass.getAnnotation(Document.class);
            collName = document.collection();
        } else {
            collName = collName.replaceFirst(collName.substring(0, 1)
                      ,collName.substring(0, 1).toLowerCase()) ;
        }
        return collName;
    }

核心其实就在于用collection执行command方法,然后将修语句转成DBObject对象,执行命令的方式来达到批量更新的操作。

当然如果不用spring data mongodb的话也可以直接封装DBObject对象的修改语句执行即可,小编这里是将data框架提供的Query和Update转成了DBObject来执行的,最终需要的还是DBObject。

如果使用原始的js语句来执行的话语法如下:

db.runCommand(
{
   update: "article_info",
   updates: [
     { q: { author: "jason" }, u: { $set: { title: "批量更新" } }, multi: true },
     { q: { author: "yinjihuan"}, u: { $set: { title: "批量更新" }}, upsert: true }
   ],
   ordered: false
}
)

官方文档:http://docs.mongodb.org/manual/reference/command/update

下面给出测试代码

List<BathUpdateOptions> list = new ArrayList<BathUpdateOptions>();
list.add(new BathUpdateOptions(Query.query(Criteria.where("author").is("yinjihuan")),
        Update.update("title", "批量更新"), true, true));
list.add(new BathUpdateOptions(Query.query(Criteria.where("author").is("jason")),
        Update.update("title", "批量更新"), true, true));
int n = MongoBaseDao.bathUpdate(mongoTemplate, Article.class, list);
System.out.println("受影响的行数:"+n);

源码下载:https://github.com/yinjihuan/cxytiandi




转自:https://www.jianshu.com/p/3577ccb722a1
 

猜你喜欢

转载自blog.csdn.net/dragonpeng2008/article/details/90175862