[英]Hibernate: org.hibernate.PersistentObjectException: detached entity passed to persist
[英]org.hibernate.PersistentObjectException: detached entity passed to persist exception
我正在创建一个简单的应用程序,只需使用Java JPA
向表中插入一行(如果表不存在,创建它)。
我正在为它的可运行示例附加一些代码。
这是我得到的例外和堆栈跟踪:
EXCEPTION -- > org.hibernate.PersistentObjectException: detached entity passed to persist: view.Person
javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: view.Person
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1187)
at view.TestJPA.main(TestJPA.java:34)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: view.Person
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:139)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181)
... 1 more
这是我的代码:
主要课程:
package view;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class TestJPA {
public static void main(String[] args) {
Person p = new Person(1, "Peter", "Parker");
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("TesePersistentUnit");
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
try {
transaction.begin();
entityManager.persist(p);
entityManager.getTransaction().commit();
}
catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
System.out.println("EXCEPTION -- > " + e.getMessage());
e.printStackTrace();
}
finally {
if (entityManager != null) {
entityManager.close();
}
}
}
}
和Person类:
package view;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "People")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private String lastName;
public Person(int id, String name, String lastName) {
this.id = id;
this.name = name;
this.lastName = lastName;
}
public Person() {
}
}
这是我的persistence.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="TesePersistentUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>view.Person</class>
<properties>
<!-- SQL dialect -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/tese_tabelas?zeroDateTimeBehavior=convertToNull"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.password" value=""/>
<!-- Create/update tables automatically using mapping metadata -->
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
-----------------------编辑-------------------------- -
我刚刚将提供程序更改为EclipseLink,并且没有进一步的更改它正在工作。 我现在很困惑。 为什么它适用于EclipseLink但是使用Hibernate会产生异常?
这样做的原因是你已经在Person
类中声明了使用auto策略生成的id,这意味着JPA
会在持久化实体时尝试插入id本身。 但是在constructor
您手动设置id变量。 由于ID是手动分配的,并且实体不存在于persistence context
因此这会导致JPA
认为您正在尝试保留与持久性上下文分离的实体,从而导致异常。
要修复它,不要在构造函数中设置id。
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
public Person(int id, String name, String lastName) {
// this.id = id;
this.name = name;
this.lastName = lastName;
}
然后尝试使用以下代码,它将允许您手动设置ID
。
只需使用@Id
注释,您可以定义哪个属性是您实体的标识符。 如果您不希望hibernate为您生成此属性,则无需使用@GeneratedValue
批注。
assigned - 允许应用程序在调用save()
之前为对象分配标识符。 如果未指定<generator>
元素,则这是默认策略。
package view;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "People")
public class Person {
@Id
//@GeneratedValue(strategy = GenerationType.AUTO) // commented for manually set the id
private int id;
private String name;
private String lastName;
public Person(int id, String name, String lastName) {
this.id = id;
this.name = name;
this.lastName = lastName;
}
public Person() {
}
}
在类定义中,您具有由持久性提供程序选择的策略(表,序列等)生成的带注释的id,但您通过构造函数初始化Person对象的id。 我认为离开id null可以解决你的问题。
你可以像这样使用这个控制器:
Person p = new Person(0, "Peter", "Parker");
然后,当JPA持续到数据库时,它将自动插入AUTO_INCREMENT
策略。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.