OrderRepositoryDiffImpl 类这个类继承自 AggregateRepositorySupport 类,并实现具体的订单存储逻辑 。
@Repository@Slf4j@Primarypublic class OrderRepositoryDiffImpl extends AggregateRepositorySupport<Order, OrderId> implements OrderRepository {//省略其他逻辑@Overrideprotected void onUpdate(Order aggregate, EntityDiff diff) {if (diff.isSelfModified()) {OrderDO orderDO = orderConverter.toData(aggregate);orderMapper.updateById(orderDO);}Diff orderItemsDiffs = diff.getDiff("orderItems");if ( orderItemsDiffs instanceof ListDiff diffList) {for (Diff itemDiff : diffList) {if(itemDiff.getType() == DiffType.REMOVED){OrderItem orderItem = (OrderItem) itemDiff.getOldValue();orderItemMapper.deleteById(orderItem.getItemId().getValue());}if (itemDiff.getType() == DiffType.ADDED) {OrderItem orderItem = (OrderItem) itemDiff.getNewValue();orderItem.setOrderId(aggregate.getId());OrderItemDO orderItemDO = orderItemConverter.toData(orderItem);orderItemMapper.insert(orderItemDO);}if (itemDiff.getType() == DiffType.MODIFIED) {OrderItem line = (OrderItem) itemDiff.getNewValue();OrderItemDO orderItemDO = orderItemConverter.toData(line);orderItemMapper.updateById(orderItemDO);}}}}}ThreadLocalAggregateManager 类这个类主要通过ThreadLocal来保证在多线程环境下,每个线程都有自己的Entity上下文 。
public class ThreadLocalAggregateManager<T extends Aggregate<ID>, ID extends Identifier<?>> implements AggregateManager<T, ID> {private final ThreadLocal<DbContext<T, ID>> context;private Class<? extends T> targetClass;public ThreadLocalAggregateManager(Class<? extends T> targetClass) {this.targetClass = targetClass;this.context = ThreadLocal.withInitial(() -> new DbContext<>(targetClass));}@Overridepublic void attach(T aggregate) {context.get().attach(aggregate);}@Overridepublic void attach(T aggregate, ID id) {context.get().setId(aggregate, id);context.get().attach(aggregate);}@Overridepublic void detach(T aggregate) {context.get().detach(aggregate);}@Overridepublic T find(ID id) {return context.get().find(id);}@Overridepublic EntityDiff detectChanges(T aggregate) throws IllegalAccessException {return context.get().detectChanges(aggregate);}@Overridepublic void merge(T aggregate) {context.get().merge(aggregate);}}SnapshotUtils 类SnapshotUtils 是一个工具类,它利用深拷贝技术来为对象创建快照 。
public class SnapshotUtils {@SuppressWarnings("unchecked")public static <T extends Aggregate<?>> T snapshot(T aggregate)throws IOException, ClassNotFoundException {ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(aggregate);ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return (T) ois.readObject();}}这个类中的 snapshot 方法采用序列化和反序列化的方式来实现对象的深拷贝,从而为给定的对象创建一个独立的副本 。注意,为了使此方法工作,需要确保 Aggregate 类及其包含的所有对象都是可序列化的 。
6. 小结在本文中,我们深入探讨了DDD(领域驱动设计)的一个核心构件 —— 仓储模式 。借助快照模式和变更追踪,我们成功解决了仓储模式仅限于操作聚合根的约束,这为后续开发提供了一种实用的模式 。
在互联网上有丰富的DDD相关文章和讨论,但值得注意的是,虽然许多项目宣称使用Repository模式,但在实际实现上可能并未严格遵循DDD的关键设计原则 。以订单和订单项为例,一些项目在正确地把订单项作为订单聚合的一部分时,却不合理地为订单项单独创建了Repository接口 。而根据DDD的理念,应当仅为聚合根配备对应的仓储接口 。通过今天的探讨,我们应该更加明确地理解和运用DDD的原则,以确保更加健壮和清晰的代码结构 。
推荐阅读
- 为什么从 MVC 到 DDD,架构的本质是什么?
- 赛尔号帕罗迪亚实战 赛尔号帕罗迪亚
- 云上VPC网络规划实战
- DDD 中关于应用架构的那些事
- pc端格斗类|男漫游VS男大枪,谁更适合你?解析职业优缺点,揭秘实战表现!
- Spring/SpringBoot中的声明式事务和编程式事务源码、区别、优缺点、适用场景、实战
- 鲤鱼|水面很大鲤鱼怎么钓?多年实战得出两个绝招,新手看懂也能连竿
- 京东快递H5项目接入vite实战
- 宠儿|塑造自我形象,让你成为职场上的宠儿:形象打造的实战技巧
- 做刀用什么钢最好(实战刀剑用什么钢好)
