我刚刚开始使用Hibernate,并了解事情。
目前我正在尝试设置一个测试环境,我可以使用HSQL内存实例来测试我的项目。
我遇到的错误是:
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: invalid schema name: TSG
以下是我项目的相关部分:
的persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
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>
正如您所看到的,我有一个peristence-unit
用于生产(工作正常)和一个内存中的HSQL用于测试(我无法开始工作)。
示例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.
}
最后,一个简单的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());
}
}
}
我确信我已经以一种奇怪的方式设置了一些东西,但正如我所说 - 这是我的第一次尝试。
这是我正在尝试做的事情:
我无法通过这个PersistenceException!
更新
好的,所以我意识到我不需要在我的测试用例的设置中设置一个显式的HSQL服务器,因为这正是我persistence-unit
中的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();
}
但是,我现在最终得到一个新错误,具体来说:
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: ALG_PPC_ALGORITHM_OUTPUT
所以我到了某处,但似乎没有创建表格。我想知道我的persistence.xml
是否存在问题?
答案 0 :(得分:3)
据我所知(并且我不是HSQL专家),您在连接URL中指定的TSG
是与目录不同的数据库名称。见http://hsqldb.org/doc/2.0/guide/databaseobjects-chapt.html#dbc_schemas_schema_objects
在HyperSQL中,每个数据库只有一个目录。目录的名称是PUBLIC。您可以使用ALTER CATALOG RENAME TO语句重命名目录。所有模式都属于此目录。目录名称与数据库的文件名无关。
正如我读到的那样,当HSQL创建数据库时,它会在该数据库中创建一个名为PUBLIC
的目录,并在该目录中创建一个名为PUBLIC
的模式。每个HSQL数据库只能有一个目录。该单一目录中可以有多个模式。
您获得的错误实际上来自于在映射中指定catalog = "tsg"
的尝试。该目录不存在。由于HSQL数据库只能包含一个目录,因此您必须将PUBLIC
目录重命名为TSG
(或更改映射)。
答案 1 :(得分:2)
您正在URL中指定服务器名称,但尝试使用导致此问题的内存数据库。
尝试将DB URL用作:
jdbc:hsqldb:mem:tsg
即
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:tsg"/>
还可以使用ALTER CATALOG RENAME TO tsg
更改默认目录名称(PUBLIC)。
编辑:要自动创建架构,请在persistence.xml中更新以下内容(hibernate.hbm2ddl.auto代替hbm2ddl.auto)
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
答案 2 :(得分:1)
您可以通过将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>
这会将您的表放入hsqldb数据库的默认公共目录中,因此您不必更改hsqldb方案。当您的单元测试使用包含同名表的多个目录时,它甚至可以工作,因为您只需在表名属性中给出不同的名称。
答案 3 :(得分:0)
设置中存在明显错误。连接URL必须指向服务器:
<property name="hibernate.connection.url" value="jdbc:hsqldb:hsql://localhost/tsg"/>