java - 如何处理实体中的任何字段更改(Spring Boot)

标签 java spring spring-boot

例如,我有 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 将为您施展“魔法” - 将您的事件发布为应用程序事件并在启动时注册您的监听器。

请注意,只有在实体存储库上调用 savesaveAll 方法后,spring-data 才会发布您的域事件,因此不保存 - 不事件

如果您希望监听器根据事务(成功、失败、之前或之后)工作,您也可以在不同的事务阶段使用 @TransactionalEventListener,而不是 @EventListener等)。

附注我在类上使用了 Lombok 注释来简化代码并通过构造函数注入(inject)字段。

关于java - 如何处理实体中的任何字段更改(Spring Boot),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73456940/

相关文章:

java - 使用 Java 在 Spark 2.0 中使用数据集的 GroupByKey

spring - 应用程序上下文加载两次

spring - Servlet 中的请求和 session

spring-boot - 停止 Spring Cloud Stream @StreamListener 监听,直到收到某些 Spring 事件

javascript - 复杂的ajax请求到spring post方法

java - 找到没有的阶乘它工作正常,但我不明白为什么它给我阶乘 0 表示没有 56、89、77 和其他一些数字

java - 在适用于 Java 的开发工具包中操作 AWS 基本 URL

java - Hibernate 7.0.2 : javax. 验证.NoProviderFoundException

java - rabbitmq 抛出 AmqpException : No method found for class [B

java - 服务无法正常工作