【发布时间】:2014-10-13 01:53:34
【问题描述】:
我正在使用 JPA 1.0(休眠实现)和 MySql 数据库。
project=em.find(Project.class,projectTO.getProjectID());
System.out.println("after find "+em.contains(project));
将 true 打印为 find() 返回托管状态对象。
em.detach(project);
System.out.println("after detach "+em.contains(project));
在对象现在处于分离状态时打印 false
em.getTransaction().begin();
em.persist(project);
在这里我试图持久化一个分离的对象。所以它应该给出一个IllegalStateException。但在这里,它给出了 MySQLIntegrityConstraintViolationException,因为它试图持久化已经存在的数据。
System.out.println("after persist "+em.contains(project));
当对象处于托管状态时,它会打印true。
em.getTransaction().commit();
所以我的问题是为什么分离的对象会被持久化?
为什么我没有根据文件得到IllegalStateException?
【问题讨论】:
-
实体是如何定义的?它有生成的 ID (
@GeneratedValue) 吗?它是否有版本字段 (@Version)?如果它没有任何这些,Hibernate 就无法将分离的对象与瞬态对象区分开来。 -
@JBNizet 我没有使用任何注释作为
@GeneratedValue或@Version。 bean 是手动填充的。 -
在这种情况下,正如我所说,Hibernate 无法区分 ID 为 56 的已分离、已持久化的实体与您要插入的 ID 为 56 的临时实体。由于您调用了 persist(),它假定它是瞬态的并尝试插入它。
-
@JBNizet 那么我应该怎么做才能纠正这个问题。?您能否详细说明“区分瞬态对象和分离对象”。
-
我给你一个对象。你怎么知道它是否存在于数据库中?如果 ID 配置为自动生成,则可以:如果对象有 ID,则它存在于数据库中。如果不是,它是一个要插入的新对象。如果它具有 Hibernate 分配的版本字段,则可以:如果版本为 0,则它从未被插入。如果没有,则已插入。如果它没有这两个中的任何一个,你就无法知道。由于您调用persist(),因此您的意图是在数据库中插入一个新对象。所以 Hibernate 做到了,但因为它已经存在而失败。