【问题标题】:Spring / JPA / Hibernate / PostgreSQL throws EntityNotFoundException in nested transactionSpring / JPA / Hibernate / PostgreSQL 在嵌套事务中抛出 EntityNotFoundException
【发布时间】:2023-04-03 06:56:02
【问题描述】:

我有以下设置: Spring -> JPA -> Hibernate -> PostgreSQL

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

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

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

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

em 是一个从 spring 注入的 EntityManager。

有什么想法吗?

你好,本

【问题讨论】:

    标签: hibernate spring postgresql jpa


    【解决方案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. 将需要事务的方法移到另一个类中。

    您可以在 Spring 文档here 中阅读更多相关信息。

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

    【讨论】:

      猜你喜欢
      • 2021-11-17
      • 1970-01-01
      • 1970-01-01
      • 2011-11-01
      • 1970-01-01
      • 2016-06-26
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多