1. 程式人生 > >detached entity passed to persist 錯誤的引起的原因和解決辦法

detached entity passed to persist 錯誤的引起的原因和解決辦法

今天在測試整合Spring和Hibernate的時候,遇到了一個問題,報錯情況如下:

報錯資訊:

org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.bean.Cat; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.bean.Cat
    at org.springframework.orm
.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:668) at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412) at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java
:411) at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374) at org.springframework.orm.hibernate3.HibernateTemplate.persist(HibernateTemplate.java:793) at com.dao.impl.CatDaoImpl.createCat(CatDaoImpl.java:20) at com.test.TestCat.testAdd
(TestCat.java:35) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.bean.Cat at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:127) at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61) at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:808) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:782) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:786) at org.springframework.orm.hibernate3.HibernateTemplate$21.doInHibernate(HibernateTemplate.java:796) at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406) ... 29 more

報錯原因:

從報錯資訊“detached entity passed to persist: com.bean.Cat”可以分析出,該錯誤是在Cat持久化轉換時出的錯。下面是測試的部分程式碼:

Cat實體類

/**
 * @Author: zsh
 * @Title: Cat.java
 * @Description:Cat實體類
 * @Date:2016年9月18日 下午3:12:23
 */
@Entity
@Table(name = "cat")
public class Cat {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(name = "name")
    private String name;

    @Temporal(value = TemporalType.TIMESTAMP)
    private Date createDate;

    ……省略了構造器及setter、getter方法。

注意:使用註解的時候,為了避免破壞Java的封裝特性,一般會寫在get方法上,此處為了方便分析,所以寫在欄位上方。

測試方法

@Test
    public void testAdd() throws ParseException{
        Cat cat = new Cat(2,"TOM",new SimpleDateFormat("yyyy-MM-dd").parse("2000-1-1"));
        cDao.createCat(cat);
    }

通過分析兩段程式碼可以發現,在實體類中設定了ID欄位的自增,但是在測試時,例項化Cat類的時候又指定了ID的值,所以在執行的時候會報出錯誤!

解決方法:

1、取消欄位自增設定
2、例項化Cat物件時不設定ID值