删除分离对象时,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的严格措辞,你的全新对象是一个实体,没有分离,所以代码没有抛出异常的错误。
问题
我正在为 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的严格措辞,你的全新对象是一个实体,没有分离,所以代码没有抛出异常的错误。