【问题标题】:Hibernate JPA detached object is persistingHibernate JPA 分离对象持续存在
【发布时间】: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 做到了,但因为它已经存在而失败。

标签: hibernate jpa


【解决方案1】:

看看下面的persist方法规范:

/**
 * Make an entity instance managed and persistent.
 * @param entity
 * @throws EntityExistsException if the entity already exists.
 * (The EntityExistsException may be thrown when the persist
 * operation is invoked, or the EntityExistsException or
 * another PersistenceException may be thrown at flush or commit
 * time.)
 * @throws IllegalStateException if this EntityManager has been closed.
 * @throws IllegalArgumentException if not an entity
 * @throws TransactionRequiredException if invoked on a
 * container-managed entity manager of type
 * PersistenceContextType.TRANSACTION and there is
 * no transaction.
 */
public void persist(Object entity);

如果 EntityManager 关闭,该方法应该只抛出 IllegalStateException。由于您的 ID 属性有一个值并且该对象超出了持久化范围,因此 JPA 将尝试持久化它,将实体作为新实体处理。

【讨论】:

    猜你喜欢
    • 2016-10-29
    • 2012-01-14
    • 2021-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 2017-10-21
    相关资源
    最近更新 更多