一种方法是使用自定义控制器和服务实现业务逻辑。但这种方式抵消了Spring数据REST的“优势”。
另一种选择(在我看来,SDR更自然)是使用
published events from aggregate roots
. 在这种情况下,您应该从
AbstractAggregateRoot
并实现一个将发布某些“事件”的方法。那么您将能够处理此事件(在
@EventListener
)在保存实体的过程中在同一事务中。例如:
@Entity
public class Order extends AbstractAggregateRoot {
//...
public void registerItems(List<Item> items) {
this.registerEvent(new RegisterItemsEvent(this, items));
}
}
@Getter
@RequiredArgsConstructor
public class RegisterItemsEvent {
private final Order order;
private final List<Item> items;
}
@RequiredArgsConstructor
@Component
public class EventHandler {
private final ItemRepo itemRepo;
@EventListener
@Transactional(propagation = MANDATORY)
public void handleRegisterItemsEvent(RegisterItemsEvent e) {
Order order = e.getOrder();
List<Item> items = e.getItems();
// update items with order - skipped...
itemRepo.saveAll(items);
}
}
用法示例:
@Component
@RepositoryEventHandler
public class OrderEventHandler {
@BeforeCreate
public void handleOrderCreate(Order order) {
// prepare a List of items - skipped...
order.registerItems(items);
}
}
Order
然后它发出
RegisterItemsEvent
handleRegisterItemsEvent
你的方法
EventHandler
在同一事务中保存准备好的项目(我们使用
propagation = MANDATORY
@Transaction
用于确保事务存在的注释)。
Domain event publication from aggregate roots
更新的
对于您的特定任务,您可以创建类
ItemChangedEvent
:
@Getter
@RequiredArgsConstructor
public class ItemChangedEvent {
private final Item item;
}
实现方法
markAsChanged
Item
实体:
@Entity
public class Item extends AbstractAggregateRoot {
//...
public void markAsChanged() {
this.registerEvent(new ItemChangedEvent(this));
}
}
当
item
更改,您将其标记为“已更改”:
@Component
@RepositoryEventHandler
public class ItemRepositoryEventHandler {
@BeforeCreate
@BeforeSave
@BeforeDelete
public void itemChanged(Item item) {
item.markAsChanged();
}
}
并将其写入
项目变更开发
同一事务中的处理程序:
@Component
public class EventHandler {
@EventListener
@Transactional(propagation = MANDATORY)
public void handleItemChangedEvent(ItemChangedEvent e) {
Item item = e.getItem();
writeToFile(item);
}
}