本着开源精神,任何Hibernate ORM问题都应该附上一个可复现的测试用例。这个测试用例证明了问题确实存在并且可以复现。
为了简化测试用例编写过程,Hibernate提供了一系列可以从GitHub获取的模板。多亏了这些测试,问题报告者可以专注于实际的持久化相关问题,因为模板负责所有启动逻辑。
之前,测试用例模板仅适用于Hibernate原生API,只要熟悉它就足够了。由于许多项目使用Hibernate作为JPA提供者,提供一个JPA启动环境也非常方便。这正是我们所做的。
接下来,我将提供一个编写基于JPA的Hibernate测试用例的逐步指南。
首先,您需要分叉或下载hibernate-test-case-templates GitHub仓库。
此仓库包含一个orm
文件夹,包含两个Maven模块
- hibernate-orm-4
-
用于复现Hibernate 4.x的问题
- hibernate-orm-5
-
用于复现Hibernate 5.x的问题
每个模块有三个模板
- ORMStandaloneTestCase.java
-
这是一个Hibernate原生测试用例(您可以访问
SessionFactory
并使用Session
),但需要您手动启动Hibernate环境。 - ORMUnitTestCase.java
-
这也是一个Hibernate原生测试用例(您可以访问
SessionFactory
并使用Session
),但启动由您负责。 - JPAUnitTestCase.java
-
这是一个新模板,用于使用Java持久化API复现问题(您可以访问
EntityManagerFactory
并使用EntityManager
)。
在使用Hibernate本地API复制问题时,通常推荐使用 |
本文将重点介绍新添加的JPAUnitTestCase
,其外观如下
public class JPAUnitTestCase {
private EntityManagerFactory entityManagerFactory;
@Before
public void init() {
entityManagerFactory = Persistence.createEntityManagerFactory( "templatePU" );
}
@After
public void destroy() {
entityManagerFactory.close();
}
// Entities are auto-discovered, so just add them anywhere on class-path
// Add your tests, using standard JUnit.
@Test
public void hhh123Test() throws Exception {
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
// Do stuff...
entityManager.getTransaction().commit();
entityManager.close();
}
}
在每个测试用例之前创建EntityManagerFactory
,并在之后销毁它。测试用例逻辑位于@Test
Junit方法内部。
您应将测试方法命名为您要复制的Hibernate JIRA问题。 |
EntityManagerFactory
使用templatePU
持久化单元,位于src/test/resources/META-INF/persistence.xml
。默认情况下,此文件看起来像这样
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="templatePU" transaction-type="RESOURCE_LOCAL">
<description>Hibernate test case template Persistence Unit</description>
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.archive.autodetection" value="class, hbm"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
<property name="hibernate.connection.url" value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.pool_size" value="5"/>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.max_fetch_depth" value="5"/>
<property name="hibernate.cache.region_prefix" value="hibernate.test"/>
<property name="hibernate.cache.region.factory_class"
value="org.hibernate.testing.cache.CachingRegionFactory"/>
<!--NOTE: hibernate.jdbc.batch_versioned_data should be set to false when testing with Oracle-->
<property name="hibernate.jdbc.batch_versioned_data" value="true"/>
<property name="javax.persistence.validation.mode" value="NONE"/>
<property name="hibernate.service.allow_crawling" value="false"/>
<property name="hibernate.session.events.log" value="true"/>
</properties>
</persistence-unit>
</persistence>
|
所有实体都是自动发现的,因此您可以将它们放在类路径上的任何位置。在本例中,我们将使用以下实体
@Entity
public class Event {
@Id
@GeneratedValue
private Long id;
@Temporal(TemporalType.TIMESTAMP )
private Date createdOn;
public Event() {
}
public Event(Date createdOn) {
this.createdOn = createdOn;
}
public Long getId() {
return id;
}
public Date getCreatedOn() {
return createdOn;
}
}
现在,可以将持久化逻辑添加到JUnit测试方法中
@Test
public void hhh123Test() throws Exception {
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
Event event = new Event( new Date() );
entityManager.persist( event );
Event dbEvent = entityManager.createQuery(
"select e " +
"from Event e", Event.class)
.getSingleResult();
assertEquals(event.getCreatedOn(), dbEvent.getCreatedOn());
entityManager.getTransaction().commit();
entityManager.close();
}
就这样!您现在可以使用标准的Java持久化API提供Hibernate测试用例。