解密DDD:高内聚对象组的维护之道( 二 )

  • 支付记录(Pay) 。用户的支付信息,包括支付渠道、支付金额、支付时间等;
  • 收货地址(Address) 。用户的收货地址;
  • 在改价流程里,需要修改 Order、OrderItem、Pay 三组实体 。
    在更新地址流程里,仅需要修改 Address 和 Order 两组实体 。
    为了满足不同的业务场景,Repository 需要具备两个高级特性:
    1. 延迟加载 。只有在第一次访问关联实体时才对其进行加载,避免过早加载但实际上并没有使用所造成资源浪费问题;
    2. 按需更新 。不管加载了多少组实体,在保存时仅对发生变更的实体进行更新,减少对底层存储引擎的操作次数,从而提升性能;
    总体来说,能够具备以下特性的 Repository 才是好的 Repository:
    1. 支持组合关系
    2. 支持继承关系
    3. 支持延迟加载
    4. 支持按需更新
    3. JPA 实例综合调研各类 ORM 框架,只有 JPA 具备上述特性,而且和 DDD 是绝配 。
    3.1. 组合关系组合是一种面向对象编程的重要概念,指一个类的对象可以将其他类的对象作为自己的组成部分 。组合在DDD中使用场景最为广泛,这也是聚合的主要工作方式 。也就是将一组对象保存到存储引擎,然后在从存储引擎中获取完整的对象组 。
    从数据视角,组合关系存在两个维度:
    1. 数量维度 。指关联关系两端对象的数量,包括
    1. 一对一:一个实体对象只能关联到另一个实体对象,例如 公司 和 营业执照,一个公司只会有一个营业执照;
    2. 一对多:一个实体对象可以关联到多个实体对象,例如 订单 和 订单项,一个订单关联多个订单项;
    3. 多对一:多个实体对象可以关联到同一个实体对象,例如 订单项 和 订单,一个订单项只属于一个订单;
    4. 多对多:多个实体对象可以互相关联,例如 社团 和 学生,一个社团包含多个学生,一个学生也可以参加多个社团;
    1. 方向维度 。指对象的引用关系
    2. 单向关联,只能从一端访问另一端,比如 订单存在订单项的引用,订单项没有到订单的引用;
    3. 双向关联,可以互相访问,订单存在订单项的引用,订单项也有到订单的引用;
    两者组合,情况更加复杂,会产生:
    1. 单向多对一
    2. 双向多对一
    3. 单向一对多
    4. 双向一对多
    5. 单向一对一
    6. 双向一对一
    聚合根是一组对象访问的入口,聚合内的所有操作都必须通过聚合根进行,所以,聚合根于其他实体的关系只能是 一对多 和 一对一;同时,所有的业务操作都是从聚合根发起,通过聚合根能关联到内部实体即可,因此也不存在双向 。综上所述,DDD 对组合进行了大量简化,实际工作中主要涉及:
    1. 单向一对一
    2. 单向一对多
    3.1.1. 单向一对一通过外键的方式实现单向一对一关系,需要在主表中添加一个指向另一个表的外键,通过外键信息获取关联数据 。
    实体如下:
    // 聚合根实现@Entity@Table(name = "order_info")public class Order{@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;// 增加 @.NEToOne 注解@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)private Pay pay;// 增加 @OneToOne 注解@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)private Address address;// 忽略其他属性}// Pay 实体实现@Entity@Table(name = "pay_info")public class Pay {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;// 忽略其他属性}// Address 实现@Entity@Table(name = "address")public class Address {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;// 忽略其他属性}插入记录后,order_Infor 表数据如下
    解密DDD:高内聚对象组的维护之道


    推荐阅读