如何处理删除具有外键关系的许多JPA实体

时间:2010-01-04 05:31:07

标签: hibernate jpa

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

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

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

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

1 个答案:

答案 0 :(得分:5)

我想到了五种方式:

  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
         }
    }
    

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

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

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

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

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