【问题标题】:EntityManager.find returns previously deleted entityEntityManager.find 返回之前删除的实体
【发布时间】:2019-11-14 15:14:09
【问题描述】:

我有如下代码,但最后一个断言失败:

@Transactional
void foo()
{
  Assert.assertNotNull(em.find(TrivialEntity.class, 1));
  Assert.assertEquals(em.createQuery("DELETE TrivialEntity WHERE id=1").executeUpdate(), 1);
  Assert.assertNull(em.find(TrivialEntity.class, 1)); // fails
}

但是,在运行此代码并检查数据库后,我看到实体已被删除。我猜第二个“find”语句只是从第一个“find”返回之前返回的结果。

我还在上面的第一条和第二条语句之后用“em.flush”尝试了上面的代码,结果没有改变。如下代码确实有效,但我不想使用“删除”:

@Transactional
void foo()
{
  Assert.assertNotNull(em.find(TrivialEntity.class, 1));
  em.remove(em.find(TrivialEntity.class, 1));
  Assert.assertNull(em.find(TrivialEntity.class, 1)); // now it passes
}

【问题讨论】:

  • 您是否尝试提交事务?使用 flush() 对数据的更改会反映在数据库中,但它仍在事务中。
  • @AlexisPavlidis 我使用的是“@Transactional”,所以当方法成功返回时事务被提交。我已确认在上述任一方法成功返回后,实体已从数据库中删除。

标签: java sql-server hibernate


【解决方案1】:

EntityManager 的工作方式是它只处理托管实体。

在您通过 createQuery 执行删除查询来删除 TrivialEntity 对象的第一种情况下,没有 TrivialEntity 对象与 entityManager 关联。

它后来起作用的原因,你使用find来检索与它间接关联的entityManager的Trivial Entity Object,这次remove起作用了。

欲了解更多信息remove

为了从数据库中删除一个对象,它必须首先是 检索(无论哪种方式),然后在活动事务中,它 可以使用remove方法删除。

如果参数不是,则 remove 会抛出 IllegalArgumentException 一个实体类的实例,或者它是一个分离的实体。

【讨论】:

  • 我刚刚从baeldung.com/… 中发现了以下内容:“需要注意的是,DML 样式的 JPQL 语句既不会影响已加载到持久性上下文中的实体实例的状态也不会影响生命周期”
猜你喜欢
  • 2012-09-06
  • 1970-01-01
  • 2018-06-02
  • 2020-09-18
  • 2014-12-26
  • 2011-04-22
  • 2016-06-09
  • 2015-09-25
  • 1970-01-01
相关资源
最近更新 更多