聚合的业务代码和资源库更新代码如何统一?
来源:3-10 优雅地实现一致性:聚合

qq_慕丝0528892
2022-04-13
问题一:
修改订单状态与当前业务相关字段, 通过实体方法修改字段值, 最后由应用层调用资源仓库进行保存
那么是否就要求资源仓库的更新方法需要和实体方法进行一对一编码?
比如当领域层通过业务分支if else做出部分字段的修改
在资源库中如何识别哪些字段需要更新?
采用null判断也不行, 因为实体设计时字段是基础类型, 默认值是0
例子(写了代码注释):
应用层
@Override
@Transactional
public void run(Map<String, Object> params) {
DeviceFailureEvent event = (DeviceFailureEvent) params.get("event");
SlotVendingMachine machine = machineRepository.getSlotVendingMachineById(
event.getMachineId());
LOGGER.info("running: {}", event.toString());
if (machine.getCurOrder() != null
&& machine.getCurOrder().getOrderId() == event.getOrderId()) {
machine.cancelOrder();
} else {
Order order = orderRepository.getOrderById(event.getOrderId());
order.cancel();
orderRepository.updateOrder(order);
}
}
领域层
public void cancel() {
state = OrderState.Canceled;
// 当业务复杂时可能会存在 if else
if (某个渠道) {
// 更新字段a
a = 1;
} else if (特别渠道) {
// 更新字段b
b = 2;
}
eventBus.post(new OrderCanceledEvent(this));
}
资源库
@Override
public void updateOrder(Order order) {
OrderDo orderDo = new OrderDo();
orderDo.setOrderId(order.getOrderId());
orderDo.setState(order.getState().code());
orderDo.setPaymentId(order.getPaymentId());
// 到了资源库, 因为字段更新判断是在domain层修改的
// 这里就不知道应该更新字段 a 还是 字段 b了
orderDo.setA(order.getA())?
orderDo.setB(order.getB())?
orderMapper.updateStateAndPayment(orderDo);
}
写回答
1回答
-
尤达_技术咖啡
2022-04-14
如果不是性能要求极高,直接统一更新所有字段就好了(也有部分存储层中间件可以识别哪些字段有变更)。如果性能要求极高,而且存储底层不支持仅更新脏字段,也可以自己实现(无非就是在内存作标记,每个字段对应一个脏位)。这个问题在qq群里有过讨论,而且也有同学给出过方案,可以加qq群参与讨论。
012022-04-16
相似问题