2010-01-04 71 views
0

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

如果采购订单与特定用户相关联,那么用户删除将不可能,因为外键违规。同样,用户可能与许多其他此类表有关系。

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

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

回答

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

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

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

  4. 照你所说的做,但将所有结果存储在某种缓存中(无论是你自己的缓存还是Hibernate的缓存,哪一个更容易控制)。因此,昂贵的操作很少会完成。另外,考虑为用户列表使用分页。

  5. 努力实现ON CASCADE SET NULL。我不知道是否有可能,也许cascade=ALL + nullable=true。检查this thread。如果您没有从您的实体生成数据库,那么请在数据库中设置ON CASCADE SET NULL

和一个相关的建议:不要使用HQL删除,因为它忽略Hibernate级联。