49

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

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();
  }
}

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

我已经尝试过在此处此处的其他类似问题中找到的建议,但无济于事(好吧,后者建议@Transactional我不能使用,但我只是在 and 之间加上了语句begin()commit()

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

@OneToOne责任吗?还是我的删除代码有问题?

4

5 回答 5

105

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

如果是这种情况,您需要按照 JPA 规范的要求清理这些关联。

于 2013-06-03T16:53:58.977 回答
30

替换关联中的cascade = CascadeType.ALLby给出了预期的结果:子记录被正确删除,而无需删除父记录。orphanRemoval = true@OneToMany

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

于 2014-04-13T15:45:02.623 回答
7

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

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

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

  5. 然后不能删除父级。没有删除,没有例外,只是 TRACE 日志中的“取消计划删除”消息。

解决方案:我删除了级联属性。找到哪个子实体阻止父删除对我来说有点困难。另外,如果我删除父实体,我不明白为什么子级联会影响。

于 2015-06-17T15:35:13.430 回答
0

我对一个有很多关系的实体有同样的问题。我所做的是将父实体设置为空,进行合并,然后进行刷新和清除,最后,使用查找和删除再次获取实体。例如:

objAgreement.setParent(null);
em.merge(objAgreement);
em.flush();
em.clear();

objAgreement= em.find(Agreement.class, objAgreement.getId())
em.remove(objAgreement);
于 2019-01-22T00:38:58.680 回答
0

除此之外,一旦您已经正确设置了 Cascade 和 Orphan,就我而言,我发现了另一个原因,即即使一切看起来都很好,即使 DELETE 在日志中但数据库没有显示任何更改,也无法进行 DELETE .

这也可能是事务性问题,但在我的情况下,删除查询中的键(在 Oracle 数据库中)是数据库中的 CHAR(8) 数据类型,在这种情况下,您可以在 Oracle 文档中找到如果您的数据不是 8 长度,则CHAR 与 VARCHAR2,其余部分用空白覆盖,并且 JPA DELETE 区分“0001”和“0001”。

我写这个回复是因为我在我的所有研究中都没有看到类似的东西,其他人可以通过这篇文章并遇到同样的问题。

干杯。

于 2018-11-06T18:44:47.373 回答