首页 > 解决方案 > 使用 JpaRepository 在指定时间后删除实体

问题描述

我正在使用 Spring Boot 和 H2 db。我有一个Product实体,我希望我的应用程序能够从数据库中删除产品,但我的要求是:首先将active标志设置为 false(然后在获取期间不会考虑此行)并在特定时间段后时间完全从数据库中删除这一行。

@Entity
@Table(name = "products")
public class Product {
    @Id
    @GeneratedValue(generator = "inc")
    @GenericGenerator(name = "inc", strategy = "increment")
    private int id;
    private boolean active = true;
    // getters & setters
}

我的服务层方法负责将active标志设置为 false 并稍后完全删除(我没有什么可以满足我要求的第二部分 -在特定时间段后完全删除

@Transactional
public void deleteProduct(int id) {
    var target = repository.findProductById(id)
            .orElseThrow(() -> new IllegalArgumentException("No product with given id"));
    target.setActive(false);
    // what should I add here to remove the target after a specific time?
}

编辑

好的,我解决了我的问题:

@Transactional
public void deleteProduct(int id) {
    var target = repository.findProductByIdAndActiveTrue(id)
            .orElseThrow(() -> new IllegalArgumentException("No product with gicen id"));
    target.setActive(false);
    // complete removal after 150 seconds
    new Thread(() -> {
        try {
            Thread.sleep(150000);
            repository.deleteById(id);
        } catch (Exception e) {
            logger.error("Error removing the product");
        }
    }).start();
}

但现在我的问题是这是否是一个安全的解决方案,因为用户现在可能启动了太多线程,所以我认为我的问题有更好的解决方案(在多线程方面更安全)

标签: multithreadingspring-bootspring-data-jpadelete-row

解决方案


我不是专家,但我认为你试图实现的是不好的做法。

我相信你应该做一个计划,例如每天一次。您应该在 db 中更新 active 值。设置一个计划,每次检查条目,如果它们的活动值为 false,则删除。像这样的东西:

public void deleteProduct(int id) {
    
    //update value to false
    repository.updateProductValue(id,false);
}

和你的调度方法:

@Scheduled(fixedRate = 150000)
public void deleteNonActiveProducts() {

        List<Product> products = repository.findAllByFalseValue();
        products.forEach(product -> repository.deleteById(product.getId());
}

有了这个,您正在做的是每 150000 毫秒重复该任务,并且该任务的每次执行都是独立且非并行的。

希望对你有用。


推荐阅读