跳转到内容

聚合根 (Aggregate Root)

🧑‍💻 作者: crag
📦 版本: 0.0.1
📄 字数(字): 0
⏳ 时长(min): 0
📅 发表于: 2026-01-27
⏱️ 更新于: 2026-01-28

什么是聚合根

术语说明
聚合(Aggregate)一组相关联的领域对象(实体 + 值对象)的集合
聚合根(Aggregate Root)聚合中的主实体,聚合中唯一能被外部直接访问的对象,负责维护整个聚合的一致性和完整性

聚合根的核心原则

  • 边界保护 外部只能通过聚合根操作聚合内的其他对象,不能直接访问聚合内的非根对象,避免数据不一致
  • 一致性保证 聚合根负责验证聚合内的所有业务规则,确保聚合内的对象状态始终符合业务约束
  • 事务原子性 一个事务只能修改一个聚合根, 从执行上避免分布式事务
  • 整体生命周期 聚合由 仓储(Repository) 整体加载和保存
  • 唯一领域标识 参考Domain Identity

聚合根设计原则

  • 高内聚,低耦合:聚合内的对象必须紧密相关(比如订单和订单项),跨聚合的对象尽量通过聚合根关联,而非直接引用
  • 最小化聚合:聚合的范围不宜过大,否则会导致维护复杂、性能下降(比如 “订单” 聚合包含订单、订单项即可,无需包含用户的所有信息)
  • 聚合根负责生命周期:聚合根管理聚合内所有对象的创建、修改、删除,外部不能直接操作这些对象

代码实现参考 (结合MyBatis-Plus)

诚然, 主子表的设计非常贴合领域对象实体概念, 主表存储聚合根对象, 子表存储聚合对象关系。

主子表怎么关联

@EntityMapping(thisField = EntityField.RRN, joinField = EntityField.MAIN_REF_KEY) 用来表示主子表关联关系,如 private List<UserRoleDO> userRoleList

BaseDO.java
java
@Getter
@Setter
public abstract class BaseDO implements Serializable {

    /**
     * 主键 rrn
     */
    @TableId(value = EntityDBField.RRN)     
    private String rrn;                     

    /**
     * 是否删除 默认0代表未删除
     */
    @TableLogic
    @TableField(value = "is_deleted", fill = FieldFill.INSERT)
    private Integer deletedFlag;

    /**
     * 版本 (乐观锁,保证数据的一致性)
     */
    @Version
    @TableField(value = "version", fill = FieldFill.INSERT)
    private Integer version;

    /**
     * 创建者
     */
    @TableField(value = EntityDBField.CREATOR, fill = FieldFill.INSERT)
    private String creator;

    /**
     * 创建时间
     */
    @TableField(value = EntityDBField.CREATE_TIME, fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    /**
     * 更新者
     */
    @TableField(value = EntityDBField.UPDATER, fill = FieldFill.INSERT_UPDATE)
    private String updater;

    /**
     * 更新时间
     */
    @TableField(value = EntityDBField.UPDATE_TIME, fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;

}

强烈建议: 子对象不要超过 2 层, 避免嵌套太深带来的性能问题

mainRefKey 字段存什么?

存上级表的唯一标识, 类比领域标识的生成, 结构为 mainRefkey.xx.xxx ... 的 Md5形式;
特殊地, 如果上级表为聚合根, 则存领域标识

BaseChildDO.java
java
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
public abstract class BaseChildDO extends BaseDO {

    /**
     * 关联主表主键
     */
    @Code
    @TableField(value = EntityDBField.MAIN_REF_KEY)  
    private String mainRefKey;                       

}

由一可爱小白兔支持