删除分离对象时,Hibernate JPA 没有异常

Hibernate JPA no exception when removing detached object

问题

我正在为 JPA 服务编写单元测试,并期望在使用新创建并因此分离的实体调用 remove() 时看到 IllegalArgumentException(有关抛出的异常,请参阅 javadoc) . 我是否误解了分离实体的概念,或者这是 Hibernate 实现中的错误?

例子

抱歉这个例子太长了,但我想包括重现问题所需的一切。

TestEntity.java

@Entity
public class TestEntity {
    @Id
    @GeneratedValue
    private Long id;
    private String value;

    // Getter and setter omitted
}

TestEntityTest.java

public class TestEntityTest {
    @Test
    public void testDeletion() {
        final EntityManager entityManager = Persistence.createEntityManagerFactory("manager1").createEntityManager();

        final TestEntity entity = new TestEntity();

        // Not expected to be contained
        assertTrue(!entityManager.contains(entity));

        try {
            entityManager.getTransaction().begin();
            entityManager.remove(entity);
            entityManager.flush();
            entityManager.getTransaction().commit();
            fail("No exception thrown");
        }catch (IllegalArgumentException e) {
            // Expected when removing a detached entity
        }
    }
}

META-INF/persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/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">
    <persistence-unit name="manager1" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>org.hibernatetest.TestEntity</class>
        <properties>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
            <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:unit-testing-jpa"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
            <property name="hibernate.max_fetch_depth" value="3"/>
        </properties>
    </persistence-unit>
</persistence>

pom.xml

<project>
    <modelVersion>4.0.0</modelVersion>
    <name>persistence service</name>
    <groupId>jpa.example</groupId>
    <artifactId>persistence-service</artifactId>
    <version>1.0</version>

    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.3.8.Final</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.10</version>
        </dependency>
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.19.0-GA</version>
        </dependency>

        <!-- TEST RESOURCES -->
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <version>2.3.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

    </dependencies>
</project>

你唯一的错误是一个全新的实体对象不是detached,而是transient,或者。查看 this flow-chart lifecycle diagram 了解更多信息。

这里的要点是对象可以处于 Hibernate 生命周期的四个阶段。

  • New/Transient 对象在数据存储中没有表示,并且不与任何上下文关联。
  • 托管对象具有上下文并且在数据存储中。
  • 分离的对象在数据存储中,但已从 Hibernate 上下文中删除
  • 删除的对象不再在数据存储中(或至少标记为删除),但仍保持与上下文的连接。

按照javadoc的严格措辞,你的全新对象是一个实体,没有分离,所以代码没有抛出异常的错误。