org.hibernate.ObjectNotFoundException:不存在具有给定标识符的行

use*_*615 11 java spring hibernate

我有一个问题,因为Hibernate 4.1.8导致以下异常:

org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [test.hibernate.TestPrepravkaOsobaSAdresou$Uvazek#2]
Run Code Online (Sandbox Code Playgroud)

我在两个实体之间有一个简单的OneToMany关联:

@Entity(name = "Ppv")
@Table(name = "PPV")
public static class Ppv {

  @Id
  Long ppvId;

  @OneToMany(fetch = FetchType.EAGER, mappedBy = "ppv")
  Set<Uvazek> uvazeks = new HashSet<Uvazek>(0);
}


@Entity(name = "Uvazek")
@Table(name = "UVAZEK")
public static class Uvazek {

  @Id
  Long uvazekId;

  @ManyToOne
  @JoinColumn(name = "PPV_FXID")
  Ppv ppv;

}
Run Code Online (Sandbox Code Playgroud)

和一个测试案例,我有一个Ppv和两个Uvazek.当我加载和分离Ppv时,删除一个与加载的Ppv相关联的Uvazek并合并Ppv我得到一个异常.

jdbcTemplate.execute("insert into PPV values(1)");
jdbcTemplate.execute("insert into UVAZEK values(2, 1)");
jdbcTemplate.execute("insert into UVAZEK values(3, 1)");

Ppv ppv = (Ppv) getSession().get(Ppv.class, 1l);
getSession().clear();

getSession().delete(getSession().get(Uvazek.class, 2l));
getSession().flush();
getSession().merge(ppv);
getSession().flush();             //Causes the exception
Run Code Online (Sandbox Code Playgroud)

在Ppv合并期间,Hibernate尝试加载已删除的Uvazek.即使Uvazek被删除,Hibernate仍然有关于它的信息

org.hibernate.collection.internal.AbstractPersistentCollection.storedSnapshot
Run Code Online (Sandbox Code Playgroud)

在uvazek的独立Ppv上.在以前的版本(<4.1.8)中,这可行.在这个简单的例子中,我可以通过添加orphanRemoval=true在Ppv上设置的uvazeks 来修复它,而不是删除uvazek从在Ppv上设置的uvazeks中删除它.

所以我的问题是:这是一个Hibernate错误还是我的不良做法?

Ang*_*ity 11

问题是尝试合并id = 2的Uvazek.Hibernate看到它有一个密钥,但它不知道对象是否是脏的,所以不清楚是否应该进行SQL更新.

但由于密钥为2,Hibernate知道对象必须存在于数据库中,因此它会尝试加载对象,以便将其与刚才在内存中接收的版本进行比较,以查看对象是否有一些待处理的修改.被同步到数据库.

但是select没有返回结果,所以Hibernate有相互矛盾的信息:一方面数据库说对象不存在.另一方面,内存中的对象表示对象必须与键2一起存在.无法确定哪个是正确的,因此ObjectNotFoundException抛出.

发生的事情是,在此版本之前,代码意外地基于同时修复的错误,因此这不再有效.

最佳做法是避免清除并仅在需要作为内存优化时使用它,通过仅清除您知道在同一会话中不会被修改或需要的对象,看看Is Session clear()被认为是有害的.