Spring / JPA / Hibernate / PostgreSQL在嵌套事务中抛出EntityNotFoundException

时间:2011-06-01 09:24:46

标签: hibernate spring postgresql jpa

我有以下设置: 春天 - > JPA - > Hibernate - > PostgreSQL的

我已经创建了一个服务层,它提供了一些“@Transactional”方法来插入数据。数据在具体情况下是必须连接到类别实体(识别关系)和一些图片实体(非识别关系)的人员实体。

由于我必须提供导入器,因此我创建了一个方法(也是@Transactional)来导入csv文件。此方法首先尝试插入类别(使用从服务层调用的DAO中使用的em.persist()可以很好地工作)。然后我添加一个新的人,它连接到我之前添加的类别(类别加载,就像它已经在数据库中一样 - > HQL查询),这也适用于该类别在正在运行的事务中是持久的。 person实体还使用em.persist()来持久化事务。

现在我创建图片实体并将它们连接到person实体。在连接它们之后,我也保存了这个人,但由于它已经存在于事务中,所以我使用了em.merge()。这里我得到一个“EntityNotFoundException()”,因为hibernate(或jpa)无法从第一步加载类别(它有一个正确的id,但似乎它看不到事务)......

所有三个方法insertCategory(),insertPerson()和addPicture()也被声明为@Transaction,因为它们在正常用例中单独使用。也许这个问题与嵌套的Transaction有关,但它似乎与em.merge()有关,因为em.persist()运行良好。

em是一个从spring注入的EntityManager。

任何想法出了什么问题?

问候本

1 个答案:

答案 0 :(得分:1)

如果使用代理(事务处理的Spring默认值),则在类 中调用方法时,将忽略@Transactional注释。以下内容不起作用:

@Transactional
public void doStuff() {
  this.doSomeOtherStuff();
}

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void doSomeOtherStuff() {
  // do some more db work here.
}

如果您确实这样做,您有两种选择:

  1. 使用AspectJ代替代理。这需要一点学习曲线。
  2. 将需要交易的方法移到另一个类中。
  3. 您可以在Spring文档here中了解更多相关信息。

    在代理模式(默认设置)下,只拦截通过代理进入的外部方法调用。这意味着实际上,自调用目标对象中的一个方法调用目标对象的另一个方法,即使被调用的方法用@Transactional标记,也不会在运行时导致实际的事务。