java 为 Hibernate 测试配置 HSQL Server
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13367653/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Configuring HSQL Server for Hibernate tests
提问by Edwardr
I'm just starting with Hibernate and getting my head around things.
我刚开始使用 Hibernate 并开始着手解决问题。
Currently I'm trying to setup a testing environment where I can use a HSQL in-memory instance to test my project.
目前我正在尝试设置一个测试环境,我可以在其中使用 HSQL 内存中的实例来测试我的项目。
The error I'm running into is:
我遇到的错误是:
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: invalid schema name: TSG
Here are the relevant parts of my project:
以下是我的项目的相关部分:
persistence.xml
持久化文件
<?xml version="1.0" encoding="UTF-8"?>
org.hibernate.ejb.HibernatePersistence com.foo.api.models.tsg.AlgPpcAlgorithmOutputEntity
org.hibernate.ejb.HibernatePersistence com.foo.api.models.tsg.AlgPpcAlgorithmOutputEntity
<persistence-unit name="TestingPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.foo.api.models.tsg.AlgPpcAlgorithmOutputEntity
</class>
<properties>
<property name="dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:tsg"/>
<property name="hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.connection.autocommit" value="true"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
As you can see, I have one peristence-unit
for production (which works fine) and one in-memory HSQL one for testing (which I can't get to work).
如您所见,我有一个peristence-unit
用于生产(工作正常)和一个用于测试的内存中 HSQL(我无法开始工作)。
An example Hibernate entity:
一个示例 Hibernate 实体:
package com.foo.api.models.tsg;
import javax.persistence.*;
import java.math.BigDecimal;
@IdClass(AlgPpcAlgorithmOutputEntityPK.class)
@Table(name = "alg_ppc_algorithm_output", schema = "", catalog = "tsg")
@Entity
public class AlgPpcAlgorithmOutputEntity {
private int parameterId;
@Column(name = "parameter_id")
@Id
public int getParameterId() {
return parameterId;
}
public void setParameterId(int parameterId) {
this.parameterId = parameterId;
}
private String matchType;
@Column(name = "matchType")
@Basic
public String getMatchType() {
return matchType;
}
// for brevity I have removed the rest of the implementation
// It was auto-generated by Hibernate and works fine in production.
}
Finally, a simple TestCase class:
最后,一个简单的 TestCase 类:
package tests.integration;
import com.foo.api.models.tsg.AlgPpcAlgorithmOutputEntity;
import com.foo.api.util.HibernateUtil;
import org.hsqldb.Server;
import org.hsqldb.persist.HsqlProperties;
import org.hsqldb.server.ServerConfiguration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tests.util.HSQLServerUtil;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import com.foo.api.KeywordManager;
import java.sql.Date;
import java.util.HashSet;
public class KeywordManagerTestCase {
private static final Logger LOG = LoggerFactory.getLogger(KeywordManagerTestCase.class);
private EntityManagerFactory eMF;
protected EntityManager eM;
@Before
public void setUp() throws Exception {
HsqlProperties props = new HsqlProperties();
props.setProperty("server.database.0", "mem:tsg");
props.setProperty("server.dbname.0", "tsg");
ServerConfiguration.translateDefaultDatabaseProperty(props);
Server hsqlServer = new Server();
hsqlServer.setRestartOnShutdown(false);
hsqlServer.setNoSystemExit(true);
hsqlServer.setProperties(props);
hsqlServer.setTrace(true);
LOG.info("Configured the HSQLDB server...");
hsqlServer.start();
LOG.info("HSQLDB server started on port " + hsqlServer.getPort() + "...");
LOG.info("Loading hibernate...");
if (eMF == null) {
eMF = Persistence.createEntityManagerFactory("TestingPersistenceUnit");
}
eM = eMF.createEntityManager();
}
/**
* shutdown the server.
* @throws Exception in case of errors.
*/
@After
public void tearDown() throws Exception {
eM.close();
HSQLServerUtil.getInstance().stop();
}
/**
* Demo test to see that the number of user records in the database corresponds the flat file inserts.
*/
@Test
public void testDemo1() {
AlgPpcAlgorithmOutputEntity entity = new AlgPpcAlgorithmOutputEntity();
entity.setParameterId(200);
entity.setMatchType("aa");
KeywordManager km;
eM.persist(entity);
HashSet<Integer> params = new HashSet<Integer>();
params.add(200);
km = new KeywordManager(eM, params, new Date[2]);
HashSet<AlgPpcAlgorithmOutputEntity> res = km.pullKeywords(params);
for (AlgPpcAlgorithmOutputEntity s : res) {
System.out.println(s.getMatchType());
}
}
}
I'm sure I have set something up in a strange way, but as I say - this is my very first stab.
我确定我以一种奇怪的方式设置了一些东西,但正如我所说 - 这是我的第一次尝试。
Here is what I'm trying to do:
这是我想要做的:
- Have the testing configuration (along with all the hibernate class mapping)for the HSQL db present in persistence.xml
- Have the HSQL db start for unit tests and create and in-memory database with my project's schema (as described in persistence.xml under the class elements).
- Create entity objects and add them to the test db at test-time so I can use the db for my integration tests.
- 为存在于persistence.xml 中的HSQL 数据库提供测试配置(以及所有休眠类映射)
- 让 HSQL 数据库开始进行单元测试,并使用我的项目模式创建内存数据库(如类元素下的persistence.xml 中所述)。
- 创建实体对象并在测试时将它们添加到测试数据库,以便我可以将数据库用于我的集成测试。
I just can't get past this PersistenceException!
我就是无法克服这个 PersistenceException!
UPDATE
更新
OK, so I realised that I didn't need to setup an explicit HSQL server in the setup of my test cases, because that's exactly what the persistence-unit
entry in my persistence.xml
is for. Also I have attempted to ALTER the CATALOG so that it matches the catalog used by my mapping classes. The setup of my test case now looks like:
好的,所以我意识到我不需要在我的测试用例的设置中设置一个显式的 HSQL 服务器,因为这正是persistence-unit
my 中的条目的persistence.xml
用途。我还尝试更改 CATALOG,使其与我的映射类使用的目录相匹配。我的测试用例的设置现在看起来像:
private EntityManagerFactory eMF;
protected EntityManager eM;
@Before
public void setUp() throws Exception {
LOG.info("Loading hibernate...");
if (eMF == null) {
eMF = Persistence.createEntityManagerFactory("TestingPersistenceUnit");
}
eM = eMF.createEntityManager();
EntityTransaction eT = null;
eT = eM.getTransaction();
eT.begin();
Query q = eM.createNativeQuery("ALTER CATALOG PUBLIC RENAME TO TSG");
q.executeUpdate();
eT.commit();
// And also it seems I need to create the schema
eT = eM.getTransaction();
eT.begin();
q = eM.createNativeQuery("CREATE SCHEMA TSG AUTHORIZATION DBA");
q.executeUpdate();
eT.commit();
}
However, I just end up with a new error now, specifically:
但是,我现在遇到了一个新错误,具体来说:
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: ALG_PPC_ALGORITHM_OUTPUT
So I'm getting somewhere but it seems the tables are not being created. I wonder if there is an issue with my persistence.xml
?
所以我到了某个地方,但似乎没有创建表。我想知道是不是我的有问题persistence.xml
?
采纳答案by Yogendra Singh
You are specifying server name in the URL but trying to use memory database, which is causing the issue.
您正在 URL 中指定服务器名称,但尝试使用内存数据库,这导致了问题。
Try using the DB URL as:
尝试将数据库 URL 用作:
jdbc:hsqldb:mem:tsg
i.e.
IE
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:tsg"/>
Also use ALTER CATALOG RENAME TO tsg
to change the default catalog name(PUBLIC).
也用于ALTER CATALOG RENAME TO tsg
更改默认目录名称(PUBLIC)。
EDIT: To auto create the schema, update below in persistence.xml (hibernate.hbm2ddl.auto in place of hbm2ddl.auto)
编辑:要自动创建架构,请在persistence.xml(hibernate.hbm2ddl.auto 代替hbm2ddl.auto)中更新以下内容
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
回答by Steve Ebersole
As far as I know (and I am not a HSQL expert), the TSG
you specify in the connection url is the database name which is not the same as the catalog. See http://hsqldb.org/doc/2.0/guide/databaseobjects-chapt.html#dbc_schemas_schema_objects
据我所知(而且我不是HSQL专家),TSG
您在连接url中指定的是与目录不同的数据库名称。请参阅http://hsqldb.org/doc/2.0/guide/databaseobjects-chapt.html#dbc_schemas_schema_objects
In HyperSQL, there is only one catalog per database. The name of the catalog is PUBLIC. You can rename the catalog with the ALTER CATALOG RENAME TO statement. All schemas belong the this catalog. The catalog name has no relation to the file name of the database.
在 HyperSQL 中,每个数据库只有一个目录。目录的名称是 PUBLIC。您可以使用 ALTER CATALOG RENAME TO 语句重命名目录。所有模式都属于这个目录。目录名称与数据库的文件名无关。
As I read that, when HSQL creates a database it creates a catalog named PUBLIC
within that database and a schema named PUBLIC
within that catalog. There can only ever be one catalog per HSQL database. There can be multiple schemas within that single catalog.
正如我读到的那样,当 HSQL 创建一个数据库时,它会创建一个PUBLIC
在该数据库中命名的目录和一个PUBLIC
在该目录中命名的模式。每个 HSQL 数据库只能有一个目录。在单个目录中可以有多个模式。
The error you are getting comes actually from the attempt to specify catalog = "tsg"
in your mapping. That catalog does not exist. Since the HSQL database can contain only one catalog, you will have to rename that PUBLIC
catalog to TSG
(or change up your mapping).
您收到的错误实际上来自尝试catalog = "tsg"
在映射中指定。该目录不存在。由于 HSQL 数据库只能包含一个目录,因此您必须将该PUBLIC
目录重命名为TSG
(或更改映射)。
回答by pharsfalvi
You can override the entity mapping for your unit test by dropping in an orm.xml file to your src/test/resources/META-INF (in case of using the maven layout). In this you can override the JPA annotation mappings. For your needs you just need to override the table location, like this:
您可以通过将 orm.xml 文件放入 src/test/resources/META-INF(在使用 maven 布局的情况下)来覆盖单元测试的实体映射。在此您可以覆盖 JPA 注释映射。根据您的需要,您只需要覆盖表位置,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" version="1.0">
<entity class="com.foo.api.models.tsg.AlgPpcAlgorithmOutputEntity">
<table name="alg_ppc_algorithm_output"/>
</entity>
</entity-mappings>
This will place your table into the default public catalog of the hsqldb database, so you don't have to alter the hsqldb scheme. It may even work when your unit test uses multiple catalogs containing tables with the same name, as you just have to give different names in the table name attribute.
这会将您的表放入 hsqldb 数据库的默认公共目录中,因此您不必更改 hsqldb 方案。当您的单元测试使用包含同名表的多个目录时,它甚至可以工作,因为您只需要在表名属性中给出不同的名称。
回答by fredt
There is an obvious error in the setup. The connection URL must point to the Server:
设置中存在明显错误。连接 URL 必须指向服务器:
<property name="hibernate.connection.url" value="jdbc:hsqldb:hsql://localhost/tsg"/>