2012-08-04 57 views
1

我使用Spring數據和Hibernate,並得到一個錯誤,當我試圖保存集ID實體:春數據+ Hibernate的

org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.snp.cm.persistency.contact.Contact; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.snp.cm.persistency.contact.Contact 
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:668) 

請幫助我,我怎麼可以更新通過JpaRepositories實體或我錯過了什麼配置?

的persistence.xml:

<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"> 
<persistence-unit name="contactManagerPU"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 

    <class>com.snp.cm.persistency.contact.Contact</class> 
    <class>com.snp.cm.persistency.contact.TelephoneNumber</class> 

    <exclude-unlisted-classes>false</exclude-unlisted-classes> 

    <properties> 
     <property name="hibernate.max_fetch_depth" value="3" /> 
    </properties> 
</persistence-unit> 

Spring上下文:

<?xml version="1.0" encoding="UTF-8" standalone="no"?><beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" 
xmlns:p="http://www.springframework.org/schema/p" xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
xmlns:util="http://www.springframework.org/schema/util" 
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd 
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd 
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd" 
default-lazy-init="true"> 

<import resource="classpath*:META-INF/spring/dbs-repository-context.xml" /> 

<!-- Activates JPA's @PersistenceContext and @PersistenceUnit (if available) 
    annotations to be detected in bean classes. --> 
<context:annotation-config /> 

<!-- Enable Transaction using @Transactional annotation --> 
<tx:annotation-driven /> 

<bean id="daTM" 
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager" 
    p:dataSource-ref="dataSource" /> 

<!-- Create local transaction manager --> 
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" 
    p:entityManagerFactory-ref="entityManagerFactory" lazy-init="true" 
    p:dataSource-ref="dataSource" /> 

<!-- Create EntityManagerFactory for injection into services. --> 
<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
    p:dataSource-ref="dataSource" p:persistenceXmlLocation-ref="persistenceXmlLocation"> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
      <property name="showSql" value="true" /> 
     </bean> 
    </property> 
</bean> 

<!-- Database access configuration --> 
<bean id="persistenceXmlLocation" class="java.lang.String"> 
    <constructor-arg value="classpath*:META-INF/persistence.xml"></constructor-arg> 
</bean> 

<context:property-placeholder 
    location="classpath:META-INF/spring/jdbc.properties" /> 

<!-- Dev's env DataSource --> 
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"> 
    <property name="driverClassName" value="${jdbc.driver}" /> 
    <property name="url" value="${jdbc.url}" /> 
    <property name="username" value="${jdbc.username}" /> 
    <property name="password" value="${jdbc.password}" /> 
</bean> 

我使用的OpenJPA在另一個項目,並沒有這樣的問題: '保存' 梅索德並創建和更新,如果一個實體已經設置了ID。那麼我如何更新一個對象呢?我應該實施我自己的更新方法嗎?

測試失敗:

@Test 
public void testRepositorySaveMethod() { 
    Contact contact = new Contact(); 
    contact.setLastName("Carter"); 
    contact.setName("John"); 
    contact.setNickName(null); 
    contact = this.contactRepository.save(contact); 
    Assert.assertNotNull(contact.getContactId()); 

    TelephoneNumber telephoneNumber1 = new TelephoneNumber(); 
    telephoneNumber1.setTelephoneNumber("777 7777777"); 
    telephoneNumber1.setContact(contact); 
    telephoneNumber1.setTelephoneType(TelephoneType.HOME); 
    this.telephoneNumberRepository.save(telephoneNumber1); // failes cause contact has already id 

    contact = this.contactRepository.findOne(contact.getContactId()); 

    Assert.assertEquals(1, contact.getTelephoneNumbers().size()); 
} 
+0

你需要顯示一些代碼。您只在這裏提供了ORM和Bean的配置。根本原因肯定是你的代碼。 – 2012-08-04 22:57:57

回答

0

一切說是:detached entity passed to persist

也許你正在試圖做類似如下:

Entity detachedEntity = getDetachedEntitySomehow(); 
em.persist(detachedEntity); // it is causing error. 

看來id設置爲你的實體的任何試圖使用persist進行更新。

你可以看看這個答案過於:「detached entity passed to persist error」 with JPA/EJB code

4

原因如下。存儲庫代理的save(…)方法是事務性的。如果您配置了JpaTransactionManager,則Hibernate Session的生命週期將綁定到該事務。當您的測試用例中的呼叫從save(…)返回時,這導致Session(和事務)關閉。因此,該實體不再附加到Session,這會導致您後來看到的異常。

測試用例中的解決方案通常是將測試方法標記爲@Transactional。假設你正在使用Spring測試上下文框架,這將導致一個事務(因此Session)被打開(並且保持打開狀態)以用於整個測試方法。

除此之外,DataSourceTransactionManager的聲明已過時,因爲您似乎沒有在任何地方使用它。

+0

是的,非常感謝,你是對的。嗯,但現在我得到了上次斷言錯誤,導致我的@OneToMany關係不起作用。 – Snoopman 2012-08-16 19:58:34

+0

@Snoopman由於電話收集是延遲加載的,並且在調用assert時會話已經關閉。 Oliver建議你用'@ Transactional'標記測試方法嗎? – 2013-11-21 15:26:58

-1

一切都是由說:通過分離的實體堅持

也許你正在試圖做類似如下:

實體detachedEntity = getDetachedEntitySomehow(); em.persist(detachedEntity); //這是導致錯誤。

似乎身份證是爲您的實體設置任何嘗試使用 持續更新。

spring-data不支持crud-repository接口中的任何更新方法。這裏的解決方案是什麼,如果它不是測試類?