【问题标题】:Spring data + HibernateSpring数据+休眠
【发布时间】:2012-08-02 11:43:31
【问题描述】:

我正在使用 Spring Data 和 Hibernate,当我尝试使用 set id 保存实体时出现错误:

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>

春天上下文:

<?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());
}

【问题讨论】:

  • 你需要展示一些代码。您在这里只提供了 ORM 和 bean 的配置。根本原因肯定是你的代码。

标签: spring hibernate spring-data spring-data-jpa


【解决方案1】:

原因如下。存储库代理的save(…) 方法是一种事务性方法。由于您配置了JpaTransactionManager,Hibernate Session 的生命周期绑定到事务。这会导致在您的测试用例中调用从save(…) 返回时关闭Session(和事务)。因此,实体不再附加到Session,这会导致您稍后看到的异常。

测试用例中的解决方法通常是将测试方法标记为@Transactional。假设您使用的是 Spring 测试上下文框架,这将导致一个事务(以及 Session)为整个测试方法打开(并保持打开状态)。

除此之外,DataSourceTransactionManager 的声明已经过时,因为您似乎没有在任何地方使用它。

【讨论】:

  • 是的,非常感谢,你是对的。嗯,但现在我在最后一次断言时遇到错误,因为我的 @OneToMany 关系不起作用。
  • @Snoopman 因为电话集合是延迟加载的,并且在调用 assert 时会话已经关闭。您是否按照 Oliver 的建议将测试方法标记为 @Transactional
【解决方案2】:

一切都说: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

【讨论】:

    猜你喜欢
    • 2016-01-26
    • 2014-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    • 2014-05-12
    • 2013-12-08
    相关资源
    最近更新 更多