spring-data-mongodb向mongodb-driver执行find指令时,后者解析后返回一个BsonDocument,BsonDocument继承自BsonValue,并且implements了Map<String, Bsonvalue>接口(内部通过LinkedHashMap实现),其成员如下,可以参考mongodb API:
1
2
3
4
5
6waitedMS --> BsonInt64
cursor --> BsonDocument
firstBatch --> BsonArrayWrapper //第一批读取到的document列表(ArrayList<Document>),当decode后被wrapper到BsonArrayWrapper
id --> BsonInt64 //游标的Id,
ns --> BsonString //NameSpace的缩写,组成为:数据库名.文档名,例如:test.Bag
ok --> bsonDouble //标明命令是否执行成功:1:成功;0:失败spring-data-mongodb的基础事件:
org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent
,可以继承AbstractMongoEventListener
,当执行document在进行删除前、删除后、存储前、存储后、转换前、转换后、加载后时,可以执行自定义操作。MongoDb生成唯一Id最佳实践(来源):
定义生成唯一Id的java类:
1
2
3
4
5
6
7
public class DatabaseSequence {
private String id;
private long seq;
}定义生成唯一Id的函数:
1
2
3
4
5
6public long generateSequence(String seqName) {
DatabaseSequence counter = mongoOperations.findAndModify(query(where("_id").is(seqName)),
new Update().inc("seq",1), options().returnNew(true).upsert(true),
DatabaseSequence.class);
return !Objects.isNull(counter) ? counter.getSeq() : 1;
}可以使用
AbstractMongoEventListener
实现自动化设置,例如:1
2
3User user = new User();
user.setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME)); //User.SEQUENCE_NAME为static string类型
user.setEmail("john.doe@example.com");
spring-data-mongodb实例化entity的算法如下所示(原文地址):
- 如果包含无参构造参数,则使用该构造函数,其他有参构造函数被忽视
- 如果只有一个含有参数的构造函数,将该构造函数将会被使用
- 如果有多个有参构造函数,那么含有
@PersistenceConstructor
注解的构造函数将会被使用。
在加载数据并创建领域对象时,Spring Data会在运行时生成对象工厂(继承自接口:ObjectInstantiator),并且调用领域对象的构造函数,而并没有使用反射,这提升了10%性能,但是如果要是用该特性必须满足以下条件(原文地址):
- 不能是私有类
- 不是是非静态的内部类
- 不能是CGLib代理类
- 被Spring Data选中的构造函数不能是私有的
Spring Data给予的一般性建议((原文地址)[https://docs.spring.io/spring-data/mongodb/docs/3.1.6/reference/html/#mapping.general-recommendations]):
- 尽量使用不可变实体对象(immutable objects)
- 如果无法将实体设计为不可变对象,那么提供一个全参构造函数,如此一来Spring Data可以将对象属性一次性赋值成功,从而跳过属性设置,最终获得最佳性能。
- 全参构造函数可以提供最佳的性能,所以要尽量避免由于出现多个重载构造函数而使用*
@PersistenceConstructor
* 注解,而要防止多个重载的构造函数,那就尽量使用静态的工厂方法 - 确保Spring Data的对象工厂(instantiator )和属性访问器(property accessor classes)可以正常被使用,也即第5条的4个条件都要被满足
- 对于标识符字段(也即将会被序列化为_id字段的属性),声明为final,并且优先使用全参构造函数,其次使用with…方法
- 使用Lombok 来避免样板代码,并且使用*
@AllArgsConstructor
*来生成全参构造函数
Spring Data在映射层处理_id字段的规则
- 如果类的成员变量被增加了
@Id
(org.springframework.data.annotation.Id
)注解,那么将会被映射为MongoDB的_id字段 - 如果类的成员变量没有
@Id
注解,但是被命名为id,那么也会被解析映射为_id字段 - 作为标识符字段的默认类成员变量名_id,并且可以被
@Field
字段注解
- 如果类的成员变量被增加了