Java 如何在DDD中管理域逻辑和事件之间的事务?
我正在研究DDD和事件源的编程 我看到一个例子,当一个域逻辑被调用时(例如,Java 如何在DDD中管理域逻辑和事件之间的事务?,java,spring,transactions,event-handling,domain-driven-design,Java,Spring,Transactions,Event Handling,Domain Driven Design,我正在研究DDD和事件源的编程 我看到一个例子,当一个域逻辑被调用时(例如,Order.placeOrder()),它将发布一个事件(例如,OrderPlaced)。事件将作为事件存储发送到MQ 域逻辑(Order.placeOrder())应该是一个原子API,如果使用Spring作为事务管理器,它应该具有@Transactional注释 现在我的问题是: 如何确保数据库更改和事件发送在同一事务中?i、 e.如果在将数据提交到数据库时出现任何错误,则事件不应发送到MQ 我知道有类似XA或2阶段
Order.placeOrder()
),它将发布一个事件(例如,OrderPlaced
)。事件将作为事件存储发送到MQ
域逻辑(Order.placeOrder()
)应该是一个原子API,如果使用Spring作为事务管理器,它应该具有@Transactional
注释
现在我的问题是:
@Transactional
注释,并且没有XA,那么在事务成功提交之后,我们是否可以执行一些逻辑?这样做的最佳实践是什么以下两个属性必须保持,才能拥有可靠的系统:
- P1:已发布的域事件必须描述实际发生的更改(即确保没有鬼事件开始四处传播)
- P2:对触发域事件的DB所做的更改必须导致事件被发布(即不要丢失事件)
- 始终先同步发布事件,然后将其持久化到数据库。这确保了P2的有效性李>
- 然后使用事件处理器检查事件流并检查是否可以在数据库中找到事件。如果不是,则从流中删除事件。这确保了P1的有效性
顺便说一下,我不同意将Spring注释添加到域对象中,而是添加到相应的应用程序服务中。这仅作为旁注。谢谢您的回复。使用与事件相同的DB确实是事务管理的一种简单方法。我认为这对于内部事件是很好的。但是,如果我们需要发布一个外部事件以供大量订阅者使用。处理案件的做法是什么?我们是否需要一个额外的调度器来将事件从DB事件存储区移动到像MQ这样的ESB产品上?@RandyHuang,这取决于您的环境。您可以使用调度程序,也可以在原始事务结束时触发“检查新域事件”。