0%

spring-data-mongodb源码阅读笔记

  1. spring-data-mongodb向mongodb-driver执行find指令时,后者解析后返回一个BsonDocument,BsonDocument继承自BsonValue,并且implements了Map<String, Bsonvalue>接口(内部通过LinkedHashMap实现),其成员如下,可以参考mongodb API

    1
    2
    3
    4
    5
    6
    waitedMS		--> BsonInt64
    cursor --> BsonDocument
    firstBatch --> BsonArrayWrapper //第一批读取到的document列表(ArrayList<Document>),当decode后被wrapper到BsonArrayWrapper
    id --> BsonInt64 //游标的Id,
    ns --> BsonString //NameSpace的缩写,组成为:数据库名.文档名,例如:test.Bag
    ok --> bsonDouble //标明命令是否执行成功:1:成功;0:失败
  2. spring-data-mongodb的基础事件:org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent,可以继承AbstractMongoEventListener,当执行document在进行删除前、删除后、存储前、存储后、转换前、转换后、加载后时,可以执行自定义操作。

  3. MongoDb生成唯一Id最佳实践(来源):

    • 定义生成唯一Id的java类:

      1
      2
      3
      4
      5
      6
      7
      @Document(collection = "database_sequences")
      @Data
      public class DatabaseSequence {
      @Id
      private String id;
      private long seq;
      }
    • 定义生成唯一Id的函数:

      1
      2
      3
      4
      5
      6
      public 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
      3
      User user = new User();
      user.setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME)); //User.SEQUENCE_NAME为static string类型
      user.setEmail("john.doe@example.com");
  1. spring-data-mongodb实例化entity的算法如下所示(原文地址):

    • 如果包含无参构造参数,则使用该构造函数,其他有参构造函数被忽视
    • 如果只有一个含有参数的构造函数,将该构造函数将会被使用
    • 如果有多个有参构造函数,那么含有@PersistenceConstructor注解的构造函数将会被使用。
  2. 在加载数据并创建领域对象时,Spring Data会在运行时生成对象工厂(继承自接口:ObjectInstantiator),并且调用领域对象的构造函数,而并没有使用反射,这提升了10%性能,但是如果要是用该特性必须满足以下条件(原文地址):

    • 不能是私有类
    • 不是是非静态的内部类
    • 不能是CGLib代理类
    • 被Spring Data选中的构造函数不能是私有的
  3. 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*来生成全参构造函数
  4. Spring Data在映射层处理_id字段的规则

    • 如果类的成员变量被增加了@Idorg.springframework.data.annotation.Id)注解,那么将会被映射为MongoDB的_id字段
    • 如果类的成员变量没有@Id注解,但是被命名为id,那么也会被解析映射为_id字段
    • 作为标识符字段的默认类成员变量名_id,并且可以被@Field字段注解