例如,我有 User
实体类。
此用户
有一个status
字段。
当 status
更改时,我需要从我的 UserService
调用方法。
我有这段代码,但我认为将服务注入(inject)实体是非常糟糕的。
@Entity
public class User {
private String status;
@Transient
private String lastStatus;
@Transient
@Autowired
private UserService userService;
public String getStatus() {
return status;
}
public void setStatus(String status) {
lastStatus = this.status;
this.status = status;
}
@PreUpdate
public void handleChangeStatus() {
if (!status.equals(lastStatus)) {
userService.doSomething();
}
}
}
最佳答案
实现此目的的一种方法是从您的 User
实体类发布域事件,然后为此事件创建监听器。
首先,让我们创建一个事件:
@AllArgsConstructor
@Getter
public class UserStatusChangeEvent {
private final UUID userId;
private final String lastStatus;
private final String newStatus;
}
然后,您的 User
实体类应使用默认域事件发布机制实现 AbstractAggregateRoot
接口(interface),以便让您的实体发布事件并在 setStatus
中发布事件> 方法:
@Entity
@Getter
public class User implements AbstractAggregateRoot<User> {
private UUID userId;
private String status;
@Transient
private String lastStatus;
public void setStatus(String status) {
lastStatus = this.status;
this.status = status;
registerEvent(new UserStatusChangeEvent(userId, lastStatus, status));
}
}
然后创建一个带有监听器的单独类,将其定义为 bean (@Component
) 并在其中注入(inject)您的 UserService
:
@RequiredArgsConstructor
@Component
public class UserStatusListener {
private final UserService userService;
@EventListener
public void onStatusChange(UserStatusChangeEvent statusChangeEvent) {
if (!statusChangeEvent.getNewStatus().equals(statusChangeEvent.getLastStatus())) {
userService.doSomething();
}
}
}
Spring 将为您施展“魔法” - 将您的事件发布为应用程序事件并在启动时注册您的监听器。
请注意,只有在实体存储库上调用 save
或 saveAll
方法后,spring-data 才会发布您的域事件,因此不保存 - 不事件。
如果您希望监听器根据事务(成功、失败、之前或之后)工作,您也可以在不同的事务阶段使用 @TransactionalEventListener
,而不是 @EventListener
等)。
附注我在类上使用了 Lombok 注释来简化代码并通过构造函数注入(inject)字段。
关于java - 如何处理实体中的任何字段更改(Spring Boot),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73456940/