【问题标题】:How to handle deletion of many JPA entities which has foreign key relationships如何处理删除许多具有外键关系的 JPA 实体
【发布时间】:2010-01-04 05:31:06
【问题描述】:

问题:实体(比如用户)在 UI 中以分页方式显示。 UI 还针对每个实体显示一个复选框,以便管理员可以多选用户并删除它们。这个实体通过外键关系与许多其他实体关联是很自然的(比如他创建的采购订单)

如果采购订单与某个用户相关联,则由于外键违规,用户将无法删除。同样,用户可能与许多其他此类表有关系。

如果无法删除实体,最好不要显示删除复选框。如果需要进行此类检查,则在为每个用户行构建用户列表页面时,您需要查询相关表以查找可能的关系。如果有很多用户,这可能是一件非常昂贵的事情。

以优雅的方式解决这个问题的建议方法是什么?

【问题讨论】:

    标签: hibernate jpa


    【解决方案1】:

    我想到了五种方法:

    1. 使用cascade=CascadeType.DELETE(或ALL)声明所有依赖项。然后所有内容都将被删除,但这很少是期望的行为。
    2. 到处显示复选框,一个一个删除用户(使用session.remove() / entityManager.remove())并捕获任何ConstraintViolationException。比如:

      for (User user : usersToDelete) {
           try {
               entityManager.remove(user); // or dao.remove(), 
                                           // or someService.remove()
           } catch (Exception ex) {
               // verify if the there is `ConstraintViolationException` 
               // in the exception chain, and log a short message about the failure
               // If the exception is elsewhere, then log the whole exception
               // or rethrow
           }
      }
      

      请注意,在这种情况下,您可能需要设置EntityManagerFlushMode,以便在正确的时间抛出异常。

    3. 编写特定于数据库的代码来检查用户(或同一场景下的任何对象)的约束。我做过一次,因为它可以准确显示哪些记录取决于当前记录。我对删除执行了特定于数据库的检查,因此所有用户都再次拥有了复选框。

    4. 照你说的做,但将所有结果存储在某种缓存中(您自己的缓存或 Hibernate 的缓存,以您更容易控制的为准)。因此,将很少进行昂贵的操作。另外,考虑对用户列表使用分页。

    5. 尝试实现ON CASCADE SET NULL。如果可能的话,我不会,也许是cascade=ALL + nullable=true。检查this thread。如果你没有从你的实体生成你的数据库,那么在数据库中设置ON CASCADE SET NULL

    还有一个相关建议:不要使用 HQL 进行删除,因为它忽略了 Hibernate 级联。

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 2019-08-16
      • 2015-08-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-06
      • 1970-01-01
      • 2021-08-08
      • 1970-01-01
      相关资源
      最近更新 更多