【问题标题】:javax.persistence.EntityNotFoundException: Unable to find object with id Xjavax.persistence.EntityNotFoundException:无法找到 id X 的对象
【发布时间】:2015-03-04 19:18:40
【问题描述】:

我正在尝试持久化一个对象,之后我想向该对象添加 2 个列表,然后对其进行更新(因为我无法使用列表持久化对象)。

所有都在一个循环中完成,第一次迭代工作得很好,从第二次我得到一个EntityNotFoundException,说没有找到 ID 来进行更新。

private Foo foo;
private FooDao dao;

for(int i = 0 ; i<10 ; i++){
  foo = new Foo();
  foo.setVar(i);

  dao.save(foo);

  generateLists(); //creates a new list every interaction 
  foo.setCatList(catList);
  foo.setBarList(barList);

  dao.update(foo);
}

如果我删除列表和更新它工作正常。

对象:

@Entity
public class Foo {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Basic(optional = false)
  private Integer id;

  @Basic(optional = false)
  @NotNull
  private String var;

  @OneToMany(cascade = CascadeType.ALL)
  private List<Bar> barList;

  @OneToMany(cascade = CascadeType.ALL)
  private List<Cat> catList;

  //Getters and Setters
}

DAO 方法:

public void save(Foo foo) {
  this.manager.joinTransaction();
  this.manager.persist(foo);
  //this.manager.flush(); Tried this, but didn't work
}

public void update(Foo foo) {
  this.manager.joinTransaction();
  this.manager.merge(foo);
}

错误:

ERROR [org.jboss.as.ejb3] (EJB default - 1) javax.ejb.EJBTransactionRolledbackException: Unable to find foo with id 4
ERROR [org.jboss.as.ejb3.invocation] (EJB default - 1) JBAS014134: EJB Invocation failed on component FooDao for method public void FooDao.atualiza(Foo): javax.ejb.EJBTransactionRolledbackException: Unable to find Foo with id 4

ps:使用这种通用方法来简化,如果需要我会发布我的解决方案(或者我称之为解决方案的混乱)

【问题讨论】:

    标签: java jpa


    【解决方案1】:

    因为您一次又一次地添加相同的列表。由于您有 OneToMany,第二个事务表明您已经保留了该列表。

    一种解决方法是改变与多对多的关系

    【讨论】:

    • 对不起,我忘记补充列表更改了,我得到的错误是当他尝试更新时说它没有找到他在保存时坚持的 ID。
    • @bacoco 你确定你第二次生成的列表具有相同的 Bar 或 Cat 对象吗?
    • @singhaskash 是的,这些列表是具有不同值的新列表,并且这些列表尚未持久化,我正在尝试通过 foo 级联更新来持久化。
    • 是的,仅在第二次迭代时更新失败。我得到一个 javax.persistence.EntityNotFoundException: Unable to find object with id X
    【解决方案2】:

    使用@ManyToOne 或@OneToOne 添加@NotFound(action = NotFoundAction.IGNORE) 很有帮助,因为..ToOne 默认为FetchType.EAGER

    【讨论】:

      【解决方案3】:

      我认为问题在于事务在您的 dAO 中的 save 方法中获取事务并提交。

      this.manager.getTransaction().commit();
      

      如果出现错误,那是因为没有活动事务,这就是刷新失败的原因。确保您在事务中,考虑使用 EntityTransaction 围绕您的 DAO 方法开始、提交和结束事务。

      如果您没有活动的 TX,您将无法将实体写入数据库,并且当您尝试合并某些内容时,找不到该实体,那么这就是您得到@的原因987654324@

      --- 更新

      当你进行合并时,Foo 对象的 ID 是什么?我认为不是正确的,或者至少是数据库中插入的最后一个 id,所以我建议先找到然后合并。

      使用

      <T> T find(java.lang.Class<T> entityClass,
                 java.lang.Object primaryKey)
      

      使用 id,并验证实例是否拥有正确的密钥

      【讨论】:

      • 对不起,你的意思是加入交易?我没有完全理解
      • Hibernate 和 JPA 与定义何时触摸数据的事务 (JTA) 一起工作,需要将某些内容刷新到数据库中这里
      • 检查这个例子,在休眠向数据库写入一些东西之前,你应该开始你的 TX,如果你不永远不会在数据库中保存一些东西,因此你正在寻找的 id 永远不会存在.mkyong.com/hibernate/quick-start-maven-hibernate-mysql-example
      • 我可能没有正确表达自己,刷新不会失败或产生错误,我尝试了 em.flush() 但它没有改变结果。至于事务,它由容器管理,因此不需要事务的开始。如果我尝试使用 .getTransaction,我会得到 java.lang.IllegalStateException: A JTA EntityManager cannot use getTransaction(),因为 JTA 正在管理事务。
      • 只是为了确认事务正在工作,如果我删除更新和孩子,一切正常,所有 foo 都被保留,但它们没有关联的猫和酒吧。
      【解决方案4】:

      我遇到了类似的问题。通过将@ManyToOne 注释更新为:

          @NotNull
          @JoinColumn(nullable = false)
          @ManyToOne(optional = false, fetch = FetchType.LAZY)
          private ParentEntityClass parent;
      
      

      添加:nullable = falseoptional = false, fetch = FetchType.LAZY 以及除此之外 - @NotNulljavax.validation.constraints.NotNull - 可能没有必要,只是为了防止 null-ables :) )

      【讨论】:

        猜你喜欢
        • 2022-09-24
        • 2020-08-19
        • 2022-07-04
        • 2019-02-17
        • 1970-01-01
        • 2016-07-12
        • 1970-01-01
        • 1970-01-01
        • 2018-04-20
        相关资源
        最近更新 更多