Spring Data MongoDB 教程

查找和更新集合中的文档

MongoCollection 上的 findAndModify(...) 方法可以更新一个文档,并在一次操作中返回旧的或新更新的文档。

MongoTemplate 提供了四个 findAndModify() 方法的重载,这些方法参数采用查询(Query)和更新(Update)类,并将文档转换为你的 POJO。

findAndModify() 方法定义如下:

// 更新文档,使用默认集合名,且返回旧对象
<T> T findAndModify(Query query, Update update, Class<T> entityClass);
// 更新文档,使用指定的集合名,且返回旧对象
<T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName);
// 更新文档,通过 FindAndModifyOptions 选项指定返回旧的还是新的文档,使用默认集合名
<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass);
// 更新文档,通过 FindAndModifyOptions 选项指定返回旧的还是新的文档,使用指定的集合名
<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass, String collectionName);

示例

以下示例将几个 Person 对象插入容器中并执行 findAndUpdate() 操作:

(1)Person 定义

package com.hxstrive.springdata.mongodb.entity;

import lombok.Builder;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.mongodb.core.mapping.Document;

/**
* 用户
* @author hxstrive.com
*/
@Document("my_person")
@TypeAlias("pers")
@Data
@Builder
@ToString
public class Person extends Contact {
   /** ID,自动映射到 MongoDB 的 _id 字段 */
   private String id;
   /** 姓名 */
   private String name;
   /** 年龄 */
   private int age;
}

(2)客户端代码

package com.hxstrive.springdata.mongodb;

import com.hxstrive.springdata.mongodb.entity.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

@SpringBootTest
class FindAndModifyTest {

   @Autowired
   private MongoTemplate mongoTemplate;

   @Test
   void contextLoads() {
       // 删除集合
       mongoTemplate.dropCollection(Person.class);

       // 准备数据
       mongoTemplate.insert(Person.builder().name("Joe").age(28).build());
       mongoTemplate.insert(Person.builder().name("Tom").age(30).build());
       mongoTemplate.insert(Person.builder().name("Helen").age(41).build());

       // 查询条件和更新对象
       Query query = new Query(Criteria.where("name").is("Joe"));
       Update update = new Update().inc("age", 40);

       // 1.修改对象,返回旧对象
       Person oldValue = mongoTemplate.update(Person.class)
               .matching(query)
               .apply(update)
               .findAndModifyValue(); // 返回旧的 person 对象
       System.out.println("旧Person name=" + oldValue.getName() + " age=" + oldValue.getAge());

       // 查询刚刚修改的最新对象
       Person newValue = mongoTemplate.query(Person.class)
               .matching(query)
               .firstValue();
       System.out.println("新Person name=" + newValue.getName() + " age=" + newValue.getAge());


       // 2.修改文档,返回新文档对象
       Person newestValue = mongoTemplate.update(Person.class)
               .matching(query)
               .apply(update)
               // 现在,在更新时返回新的文档
               .withOptions(FindAndModifyOptions.options().returnNew(true))
               .findAndModifyValue();
       System.out.println("新Person name=" + newestValue.getName() + " age=" + newestValue.getAge());

       // 3.修改文档,使用多个参数的 findAndModify 方法
       newestValue = mongoTemplate.findAndModify(query, update,
               FindAndModifyOptions.options().returnNew(true), Person.class);
       System.out.println("新Person name=" + newestValue.getName() + " age=" + newestValue.getAge());
   }

}

运行代码,输出结果:

旧Person name=Joe age=28
新Person name=Joe age=68
新Person name=Joe age=108
新Person name=Joe age=148

FindAndModifyOptions 的方法能让你设置 returnNew、upsert 和 remove 选项。下面是一个从前面的代码片断延伸出来的例子:

package com.hxstrive.springdata.mongodb;

import com.hxstrive.springdata.mongodb.entity.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

@SpringBootTest
class FindAndModifyTest2 {

   @Autowired
   private MongoTemplate mongoTemplate;

   @Test
   void contextLoads() {
       // 删除集合
       mongoTemplate.dropCollection(Person.class);

       // 准备数据
       mongoTemplate.insert(Person.builder().name("Joe").age(28).build());
       mongoTemplate.insert(Person.builder().name("Tom").age(30).build());
       mongoTemplate.insert(Person.builder().name("Helen").age(41).build());

       // 查询条件和更新对象
       Query query = new Query(Criteria.where("name").is("Bill"));
       Update update = new Update().inc("age", 40);

       // 修改对象
       // 返回新对象
       // 如果查询条件匹配到文档,则执行修改动作。
       // 如果查询条件未匹配到文档,则执行插入操作(文档内容=查询+更新)。
       Person upserted = mongoTemplate.update(Person.class)
               .matching(query)
               .apply(update)
               .withOptions(FindAndModifyOptions.options().upsert(true).returnNew(true))
               .findAndModifyValue();

       System.out.println("Person name=" + upserted.getName() + " age=" + upserted.getAge());
   }

}

执行完成后,效果如下图:

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号