在内存中使用 H2 数据库不会在单元测试中保留对象
Using H2 Database In-Memory does not persist Objects in Unit Tests
我在 persistence.xml 中遇到关于 JPA 的单元测试问题。
将对象持久化到内存中的数据库 H2 时发生错误:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running some.class.MyClass
################################################################################
BeforeClass Start
################################################################################
EntityManager is being created..
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.541 sec <<< FAILURE!
Results :
Tests in error:
some.class.MyClass: getSingleResult() did not retrieve any entities
我确信持久存在问题,而不是获取数据问题,因为 DEV 应用程序中的读取方法与真实数据库完美配合。
这是我的 persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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">
<persistence-unit name="TestPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>all entities</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.logging.level" value="SEVERE"/>
<!-- ALL SEVERE -->
<property name="eclipselink.logging.level.sql" value="SEVERE"/>
<!-- ALL SEVERE -->
<property name="eclipselink.logging.parameters" value="true"/>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test;MODE=Oracle;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS DEV"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<!-- model creation have to be done via javax.persistence, not hibernate/eclipselink - otherwise import doesn't works -->
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.create-source" value="metadata"/>
<property name="javax.persistence.schema-generation.drop-source" value="metadata"/>
</properties>
</persistence-unit>
</persistence>
</persistence-unit>
这是一段 Java 代码:
@BeforeClass
public static void setUpClass() {
myOut("BeforeClass Start");
EM = Persistence.createEntityManagerFactory(PU).createEntityManager();
myOut("EntityManager is being created..");
EM.persist(new Account(PU, PU, PU));
EM.persist(new Account(PU + "2", "dsaddsa", "dsadas"));
EM.persist(new Account(PU + "3", "saddsd", "dsadasa"));
EM.persist(new Account(PU + "4", "adsada", "hdsd"));
final DaoLogged dao = new DaoLogged();
dao.setEntityManager(EM);
dao.getAccountByLogin(PU);
myOut("BeforeClass Done.");
}
单一结果方法:
public Account getAccountByLogin(String login) {
return (Account) getEntityManager().createNamedQuery("Account.findByLogin").setParameter("login", login).getSingleResult();
}
我将不胜感激任何帮助! :)
问候!
[编辑]
我一直在寻找答案,实际上在今天早上这完全没有用,但是经过几个小时的编辑,搜索互联网我坚持了下来..
[编辑 2]
我把上面的方法改成了:
@BeforeClass
public static void setUpClass() {
myOut("BeforeClass Start");
EM = Persistence.createEntityManagerFactory(PU).createEntityManager();
myOut("EntityManager is being created..");
**EM.getTransaction().begin();**
EM.persist(new Account(PU, PU, PU));
EM.persist(new Account(PU + "2", "dsaddsa", "dsadas"));
EM.persist(new Account(PU + "3", "saddsd", "dsadasa"));
EM.persist(new Account(PU + "4", "adsada", "hdsd"));
**EM.getTransaction().commit();
EM.flush();
EM.getTransaction().begin();**
final DaoLogged dao = new DaoLogged();
dao.setEntityManager(EM);
dao.getAccountByLogin(PU);
myOut("BeforeClass Done.");
}
仍然是错误,但有所不同:
javax.persistence.TransactionRequiredException:
异常说明:当前没有交易活动
错误意味着查询没有return任何结果。确保数据库设置正确。为此,为 EclipseLink 启用 DEBUG
日志级别。那应该向您显示正在发送到数据库的 SQL。
您还需要一个事务管理器。如何设置和配置取决于您的应用程序的体系结构。事务管理器负责协调事务的所有不同参与者(数据库、EntityManager
,有时还有其他各方,如 JMS)。
如果您使用Spring,那么事务管理器会自动将事务与测试同步。
注意尽量在每次测试前启动事务,每次测试后回滚。这样,测试 #2 就不会因为测试 #1 在数据库中留下垃圾而失败。
好的,我花了一些时间来解决这些错误。:)
- 交易是必要的,在这种情况下
flush
应该在 commit
之前调用
- 我忘记向 POM 中的 eclipselink 依赖项添加范围
test
- Lombok 不会导致任何错误
- 查询格式正确,在主项目中(到目前为止我在这里称之为 'DEV')它们没有导致任何错误
Sequence Generator
是测试所必需的!
我在 persistence.xml 中遇到关于 JPA 的单元测试问题。 将对象持久化到内存中的数据库 H2 时发生错误:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running some.class.MyClass
################################################################################
BeforeClass Start
################################################################################
EntityManager is being created..
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.541 sec <<< FAILURE!
Results :
Tests in error:
some.class.MyClass: getSingleResult() did not retrieve any entities
我确信持久存在问题,而不是获取数据问题,因为 DEV 应用程序中的读取方法与真实数据库完美配合。
这是我的 persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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">
<persistence-unit name="TestPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>all entities</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.logging.level" value="SEVERE"/>
<!-- ALL SEVERE -->
<property name="eclipselink.logging.level.sql" value="SEVERE"/>
<!-- ALL SEVERE -->
<property name="eclipselink.logging.parameters" value="true"/>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test;MODE=Oracle;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS DEV"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<!-- model creation have to be done via javax.persistence, not hibernate/eclipselink - otherwise import doesn't works -->
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.create-source" value="metadata"/>
<property name="javax.persistence.schema-generation.drop-source" value="metadata"/>
</properties>
</persistence-unit>
</persistence>
</persistence-unit>
这是一段 Java 代码:
@BeforeClass
public static void setUpClass() {
myOut("BeforeClass Start");
EM = Persistence.createEntityManagerFactory(PU).createEntityManager();
myOut("EntityManager is being created..");
EM.persist(new Account(PU, PU, PU));
EM.persist(new Account(PU + "2", "dsaddsa", "dsadas"));
EM.persist(new Account(PU + "3", "saddsd", "dsadasa"));
EM.persist(new Account(PU + "4", "adsada", "hdsd"));
final DaoLogged dao = new DaoLogged();
dao.setEntityManager(EM);
dao.getAccountByLogin(PU);
myOut("BeforeClass Done.");
}
单一结果方法:
public Account getAccountByLogin(String login) {
return (Account) getEntityManager().createNamedQuery("Account.findByLogin").setParameter("login", login).getSingleResult();
}
我将不胜感激任何帮助! :) 问候!
[编辑]
我一直在寻找答案,实际上在今天早上这完全没有用,但是经过几个小时的编辑,搜索互联网我坚持了下来..
[编辑 2]
我把上面的方法改成了:
@BeforeClass
public static void setUpClass() {
myOut("BeforeClass Start");
EM = Persistence.createEntityManagerFactory(PU).createEntityManager();
myOut("EntityManager is being created..");
**EM.getTransaction().begin();**
EM.persist(new Account(PU, PU, PU));
EM.persist(new Account(PU + "2", "dsaddsa", "dsadas"));
EM.persist(new Account(PU + "3", "saddsd", "dsadasa"));
EM.persist(new Account(PU + "4", "adsada", "hdsd"));
**EM.getTransaction().commit();
EM.flush();
EM.getTransaction().begin();**
final DaoLogged dao = new DaoLogged();
dao.setEntityManager(EM);
dao.getAccountByLogin(PU);
myOut("BeforeClass Done.");
}
仍然是错误,但有所不同:
javax.persistence.TransactionRequiredException:
异常说明:当前没有交易活动
错误意味着查询没有return任何结果。确保数据库设置正确。为此,为 EclipseLink 启用 DEBUG
日志级别。那应该向您显示正在发送到数据库的 SQL。
您还需要一个事务管理器。如何设置和配置取决于您的应用程序的体系结构。事务管理器负责协调事务的所有不同参与者(数据库、EntityManager
,有时还有其他各方,如 JMS)。
如果您使用Spring,那么事务管理器会自动将事务与测试同步。
注意尽量在每次测试前启动事务,每次测试后回滚。这样,测试 #2 就不会因为测试 #1 在数据库中留下垃圾而失败。
好的,我花了一些时间来解决这些错误。:)
- 交易是必要的,在这种情况下
flush
应该在commit
之前调用
- 我忘记向 POM 中的 eclipselink 依赖项添加范围
test
- Lombok 不会导致任何错误
- 查询格式正确,在主项目中(到目前为止我在这里称之为 'DEV')它们没有导致任何错误
Sequence Generator
是测试所必需的!