JPA/休眠 - 在预删除处理程序中阻止删除?
问题标题基本上说明了一切。在 JPA/Hibernate 中,是否可以优雅地阻止从数据库中删除实体?我想将实体标记为“隐藏”,而不是实际删除它。
我还希望保留语义,这样,如果我尝试删除拥有其他实体集合的实体,则拥有实体及其集合中的每个实体都会被标记为隐藏,而无需我进行任何额外的工作,除了实现防止删除并将实体标记为隐藏的处理程序之外。Cascade
@PreRemove
这是可能的,还是我需要找出其他方法?
问题标题基本上说明了一切。在 JPA/Hibernate 中,是否可以优雅地阻止从数据库中删除实体?我想将实体标记为“隐藏”,而不是实际删除它。
我还希望保留语义,这样,如果我尝试删除拥有其他实体集合的实体,则拥有实体及其集合中的每个实体都会被标记为隐藏,而无需我进行任何额外的工作,除了实现防止删除并将实体标记为隐藏的处理程序之外。Cascade
@PreRemove
这是可能的,还是我需要找出其他方法?
在 JPA/Hibernate 中,是否可以优雅地阻止从数据库中删除实体?
是的,只要你避免使用这个是可能的。如果您确实使用 ,则 JPA 提供程序将使用相应的 SQL DELETE 语句来标记要删除的对象,这意味着一旦您标记要删除的对象,就不可能有一个优雅的解决方案。EntityManager.remove(entity)
EntityManager.remove()
在 Hibernate 中,您可以使用@SQLDelete
和@Where
注释来实现此目的。但是,这不适用于 JPA,因为已知会忽略注释中指定的过滤器。EntityManager.find()
@Where
因此,仅 JPA 解决方案涉及在实体类中添加一个标志(即一列),以将数据库中逻辑上已删除的实体与“活动”实体区分开来。您需要使用适当的查询(JPQL 和本机查询)来确保逻辑上删除的实体在结果集中不可用。可以使用 和 注释挂接到实体生命周期事件,以确保在持久和更新事件上更新标志。同样,您需要确保不会调用该方法。@PreUpdate
@PrePersist
EntityManager.remove
我本来建议使用注释来挂接到为删除实体而触发的生命周期事件,但是由于以下原因,使用实体侦听器来防止删除充满了麻烦:@PreRemove
SQL DELETE
EntityManager
EntityManager.persist
SQL DELETE
如果可以选择使用 EclipseLink 而不是 Hibernate,那么如果您定义适当的描述符自定义程序
或使用 AdditionalCriteria
注释,似乎可以找到一个优雅的解决方案。这两种操作似乎都与 和 调用配合得很好。但是,您可能仍然需要编写 JPQL 或本机查询来考虑逻辑上删除的实体。EntityManager.remove
EntityManager.find
如果删除对象以将其删除,则随后对该对象调用 persist,它将复活该对象,并且它将再次变为持久性。如果这是有意的,则可能需要这样做,但 JPA 规范也要求此行为才能使级联持续存在。因此,如果删除某个对象,但忘记从级联持久关系中删除对该对象的引用,则将忽略该删除。