JPA/Hibernate删除实体有时不起作用

Luc*_*sca 31 hibernate jpa cascading-deletes

我有以下通常运作良好的代码:

public void delete(T object)
{
  EntityManager em = getPersistence().createEntityManager();
  EntityTransaction et = em.getTransaction();
  try
  {
    et.begin();
    object = em.find(object.getClass(), object.getId());
    em.remove(object);
    em.flush();
    et.commit();
  }
  catch(Exception e)
  {
    error("Unable to delete " + object.toString() + ": there are references to it.");
  }
  finally
  {
    if (et.isActive()) et.rollback();
    em.close();
  }
}
Run Code Online (Sandbox Code Playgroud)

对于我的许多实体类,这只是有效的.但是对于其中两个它什么都不做,它不会抛出任何异常,也不会删除该对象.来自hibernate的日志显示hibernate执行了许多选择查询,但它甚至没有尝试执行删除.

我已经尝试过其他类似问题发现的建议在这里这里,但无济于事(当然,后者意味着@Transactional我不能使用,但我只是封闭之间的语句begin()commit()代替).

我似乎无法找到这两个类比其他类更多(或更少)的东西.它们@PrimaryKeyJoinColumn就像我拥有的​​几乎所有其他实体一样使用,它们具有@OneToMany并且@ManyToOne就像ohters一样.说实话,他们确实有一个@OneToOne(optional = false)引用另一个类的字段,而其他实体没有这个字段,但我不会经历改变那个(并因此改变数据库模式)的麻烦,除非你告诉我可能有一个原因为了它.

@OneToOne责任吗?或者我的删除代码是否被窃听?

Ste*_*ole 85

您是否在此图表中有关联,将持久性级联反馈到要删除的内容?如果是这样,JPA规范明确规定提供者在这种情况下取​​消删除.如果是这种情况,Hibernate会写出一条日志语句,说"取消调度实体删除[...]".您可以通过在org.hibernate.event.internal.DefaultPersistEventListener记录器上启用跟踪日志记录来查看.

如果是这种情况,您需要根据JPA规范的要求清理这些关联.

  • 如果你需要级联保持,你可以把它留在那里.只需确保在删除实体之前,您的代码会将其从父列表中删除,并将父项设置为null. (5认同)
  • 我不知道如何为org.hibernate.event.internal.DefaultPersistEventListener启用日志记录:/ (5认同)
  • 这种行为无声地发生有点难过. (5认同)
  • “..JPA 规范明确指出,在这种情况下,提供者将取消删除..”。你能参考描述这个的页面吗?我正在用“取消”这个词搜索规范,但没有找到任何东西。 (4认同)
  • 如何进行清理?这里:http://stackoverflow.com/a/26368210/498531 (3认同)

小智 26

更换cascade = CascadeType.ALLorphanRemoval = true@OneToMany联想给出了预期的结果:孩子的记录,而不需要删除父记录正确删除.

可惜没有更清楚地记录错误.

  • 如果父母负责删除,这是好的; 但是,如果子项负责删除,则可以通过从父项中删除元素(销毁引用),然后删除子项来完成. (2认同)

And*_*nyk 5

当我把事情聚集在一起时,我遇到了同样的问题。

  1. 休眠3.6.10。最终
  2. 父实体,引用子实体。
  3. 一些子实体参考父。它是遗留代码。

    class ChildEntity {
      @ManyToOne(cascade = CascadeType.ALL)
      private ParentEntity parent;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 子实体被加载到会话上下文中,然后在事务内没有JPA通知的情况下从表中删除(存储过程,本机sql)

  5. 这样就无法删除父级。没有删除,没有例外,只是TRACE日志中的“计划外删除”消息。

解决方案:我删除了层叠属性。我很难找到哪个子实体阻止了父删除。此外,我不理解为什么如果删除父实体,子级联会受到影响。