问题:实体(比如用户)在UI中以分页方式显示。 UI还显示针对每个实体的复选框,以便管理员可以多选用户并删除它们。很自然,这个实体通过外键关系与许多其他实体相关联(比如他创建的采购订单)
如果采购订单与某个用户相关联,则由于外键违规,将无法删除用户。同样,User可能与许多其他此类表有关系。
如果无法删除实体,最好不要显示删除复选框。如果需要进行此类检查,则在为每个用户行构建用户列表页面时,需要查询从属表以查找可能的关系。如果有很多用户,这可能是一件非常昂贵的事情。
以优雅的方式解决这个问题的建议方法是什么?
答案 0 :(得分:5)
我想到了五种方式:
cascade=CascadeType.DELETE
(或ALL
)声明所有依赖项。然后所有这些都将被删除,但这很少是理想的行为。在任何地方显示复选框,逐个删除用户(使用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}},以便在正确的时间抛出异常。
编写特定于数据库的代码,用于检查用户(或同一场景下的任何对象)的约束。我这样做了一次,因为它允许准确显示哪些记录取决于当前记录。我在删除时执行了特定于数据库的检查,因此所有用户都有了复选框。
按照你的说法执行操作,但将所有结果存储在某种缓存中(您自己的缓存或Hibernate的缓存,无论哪种更容易控制)。因此,很少进行昂贵的操作。另外,请考虑为用户列表使用分页。
尝试实现EntityManager
。如果有可能,我不会,ON CASCADE SET NULL
+ cascade=ALL
。检查this thread。如果您没有从实体生成数据库,那么juts会在数据库中设置nullable=true
。
还有一个相关建议:不要使用HQL进行删除,因为它忽略了Hibernate级联。