Skip to content

feat(mybatis): add repository extension points for aggregates with child tables - #73

Merged
poppycoderr merged 2 commits into
mainfrom
feat/repository-child-hooks
Oct 2, 2026
Merged

poppycoderr merged 2 commits into
mainfrom
feat/repository-child-hooks

Conversation

@poppycoderr

Copy link
Copy Markdown
Owner

Background

GenericRepositoryImpl maps one aggregate to one row: E → P, one mapper call, P → E. An aggregate with child entities, such as an order with its lines, did not fit. A subclass had to override create, update, find, findAll, page and remove, and re-implement the optimistic-lock check and the event publishing that the base class does around them. This came up when starting the order context of the ddk-mall reference application.

Changes

  • Four protected no-op methods on GenericRepositoryImpl, called around the root table's reads and writes in the same transaction:
create / createAll   insert root            → afterInsert(po)        → map to entity → publish events
update / updateAll   update root (version)  → afterUpdate(po)        → map to entity → publish events
                     0 rows                 → ConcurrentUpdateException, afterUpdate is not called
find / findAll / page   select roots        → afterLoad(pos)         → map to entities
remove / removeAll   beforeRemove(keys)     → delete roots
  • The PO carries the children in a field marked @TableField(exist = false). The E → P converter fills it, afterInsert / afterUpdate write it to the child table, and afterLoad reads it back for the P → E converter. The aggregate is still saved and loaded as a whole; the application layer does not see the child table.
  • afterLoad receives all roots of one query, so children can be fetched with a single IN query instead of one query per root.

Existing repositories are unaffected: the methods do nothing unless overridden.


背景

GenericRepositoryImpl 把一个聚合映射成一行:E → P,调用一次 Mapper,P → E。带子实体的聚合(例如订单和订单行)放不进这个模型。子类只能把 create、update、find、findAll、page、remove 全部覆盖,再把基类围绕它们做的乐观锁校验和事件发布重写一遍。这个问题是在开始做 ddk-mall 参考应用的订单上下文时遇到的。

改动

  • GenericRepositoryImpl 新增四个默认为空的 protected 方法,在根表读写的前后调用,与根表在同一个事务里,调用时机见上文。
  • PO 用标了 @TableField(exist = false) 的字段带上子对象:E → P 的转换器填好它,afterInsert / afterUpdate 把它写进子表,afterLoad 把它读回来交给 P → E 的转换器。聚合仍然作为一个整体保存和加载,应用层看不到子表。
  • afterLoad 一次拿到本次查询的全部根对象,子表可以用一条 IN 查询取回,而不是每个根对象查一次。

现有的仓储不受影响:这些方法不覆盖就什么都不做。

@poppycoderr
poppycoderr merged commit b35aa0d into main Oct 2, 2026
4 checks passed
@poppycoderr
poppycoderr deleted the feat/repository-child-hooks branch October 2, 2026 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant