MongoTemplate 上有几个便捷方法,用于保存和插入你的对象。为了对转换过程有更精细的控制,你可以用 MappingMongoConverter 注册 Spring 转换器 —— 例如 Converter<Person, Document> 和 Converter<Document, Person>。
注意:插入操作和保存操作的区别在于,如果对象不存在,则保存操作将执行插入操作。
使用保存操作的简单情况是保存一个 POJO。在这种情况下,集合名称是由类的名称(非完全限定,如 com.hxstrive.springdata.mongo.entity.Person 对象对应的集合名称为 Person)决定的。你也可以用一个特定的集合名称来调用保存操作。你可以使用映射元数据来重写存储对象的集合。
当插入或保存时,如果 id 属性没有被设置,假设它的值将由数据库自动生成。因此,为了成功地自动生成一个 ObjectId,你的类中的 id 属性或字段的类型必须是 String、ObjectId 或 BigInteger。
以下示例显示了如何保存文档并检索其内容:
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.MongoTemplate; import java.util.List; import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Query.query; import static org.springframework.data.mongodb.core.query.Update.update; @SpringBootTest public class SaveTest { @Autowired private MongoTemplate mongoTemplate; @Test void contextLoads() { Person p = Person.builder().name("Joe").age(34).build(); // 将对象插入到数据库中 mongoTemplate.save(p); System.out.println("Save: " + p); // 查找数据 p = mongoTemplate.findOne(query(where("name").is("Joe")), Person.class); System.out.println("Found: " + p); } }
运行示例,输出如下:
Save: Person(id=63a94f3810de9701d9105fb2, name=Joe, age=34) Found: Person(id=63a94f3810de9701d9105fb2, name=Joe, age=34)
以下的插入和保存操作是可用的:
void save(Object objectToSave) 将对象保存到默认的集合中,即和类名一致的集合
void save(Object objectToSave, String collectionName) 将对象保存到指定的集合中
一组类似的插入操作也是可用的:
void insert(Object objectToSave) 插入对象到默认的集合中,即和类名一致的集合
void insert(Object objectToSave, String collectionName) 插入对象到指定的集合中
Spring Data MongoDB 提供了两种方法指定我们的对象将被保存到哪个集合中,它们分别如下:
(1)默认使用的集合名是将类名改为以小写字母开头,因此一个 com.test.Person 类被存储在 person 集合中。
(2)通过 @Document 注解指定一个集合名称来保存对象。例如:
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; // 通过 @Document 注解指定集合名称为 my_person @Document("my_person") @TypeAlias("pers") @Data @Builder @ToString public class Person extends Contact { /** 自动映射到 MongoDB 的 _id 字段 */ private String id; private String name; private int age; }
(3)在调用 MongoTemplate 保存/插入方法时的最后一个参数指定集合名称,来覆盖该默认集合名称。例如:
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.MongoTemplate; import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Query.query; @SpringBootTest public class SaveTest2 { @Autowired private MongoTemplate mongoTemplate; @Test void contextLoads() { Person p = Person.builder().name("Joe").age(34).build(); // 将对象插入到数据库中 // 手动指定集合名称为 coll_person mongoTemplate.save(p, "coll_person"); System.out.println("Save: " + p); // 查找数据 // 手动指定集合名称为 coll_person p = mongoTemplate.findOne(query(where("name").is("Joe")), Person.class, "coll_person"); System.out.println("Found: " + p); } }
MongoDB 驱动程序支持在单个操作中插入文档集合,MongoOperations 接口中的以下方法支持此功能:
insert:插入一个对象,如果存在具有相同 id 的现有文档,则会生成一个错误。
insertAll:接受一个对象的集合作为第一个参数。这个方法检查每个对象,并根据前面指定的规则,将其插入到适当的集合中。
save: 保存对象,覆盖任何可能有相同id的对象。
示例:
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.MongoTemplate; @SpringBootTest public class InsertSaveTest { @Autowired private MongoTemplate mongoTemplate; @Test void contextLoads() { Person p1 = Person.builder().id("1024").name("Joe").age(34).build(); Person p2 = Person.builder().id("1024").name("Tom").age(30).build(); // 将对象插入到数据库中 // OK mongoTemplate.save(p1); System.out.println("Save p1 = " + p1); // OK mongoTemplate.save(p2); System.out.println("Save p2 = " + p2); // Error // nested exception is com.mongodb.MongoWriteException: Write operation error on server localhost:27017. // Write error: WriteError{code=11000, message='E11000 duplicate key error collection: test.my_person // index: _id_ dup key: { : "1024" }', details={}}. mongoTemplate.insert(p1); System.out.println("Insert p1 = " + p1); } }
MongoDB 驱动支持在一个操作中插入一个文档集合,MongoOperations 接口中的以下方法支持此功能:
insert:该方法以一个集合作为第一个参数。它们在一次批量写入数据库中插入一个对象的列表。
示例:
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.MongoTemplate; import java.util.ArrayList; import java.util.List; @SpringBootTest public class BatchInsertTest { @Autowired private MongoTemplate mongoTemplate; @Test void contextLoads() { Person p1 = Person.builder().id("1024").name("Joe").age(34).build(); Person p2 = Person.builder().id("1025").name("Tom").age(30).build(); Person p3 = Person.builder().id("1026").name("Helen").age(39).build(); List<Person> personList = new ArrayList<>(); personList.add(p1); personList.add(p2); personList.add(p3); // OK //mongoTemplate.insert(personList, Person.class); // OK mongoTemplate.insert(personList, "my_persson"); } }
注意,如果 List 中存在 ID 相等的对象,则保存失败,直到抛出异常的位置开始均保存失败,抛出异常之前的能够正常保存。