3

我刚刚开始使用 Hibernate 并开始思考问题。

目前我正在尝试设置一个测试环境,我可以在其中使用 HSQL 内存实例来测试我的项目。

我遇到的错误是:

javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: invalid schema name: TSG

以下是我项目的相关部分:

持久性.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());
        }

    }


}

我确信我已经以一种奇怪的方式设置了一些东西,但正如我所说 - 这是我的第一次刺伤。

这是我正在尝试做的事情:

  • 在 persistence.xml 中包含 HSQL 数据库的测试配置(以及所有休眠类映射)
  • 让 HSQL db 开始进行单元测试,并使用我的项目模式创建内存数据库(如类元素下的 persistence.xml 中所述)。
  • 创建实体对象并在测试时将它们添加到测试数据库,以便我可以将数据库用于我的集成测试。

我就是无法通过这个 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

4

4 回答 4

3

据我所知(而且我不是 HSQL 专家),TSG您在连接 url 中指定的是与目录不同的数据库名称。请参阅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(或更改您的映射)。

于 2012-11-13T21:30:14.700 回答
2

您在 URL 中指定服务器名称,但尝试使用导致问题的内存数据库。

尝试使用 DB URL:

           jdbc:hsqldb:mem:tsg

IE

  <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"/>
于 2012-11-13T21:09:30.410 回答
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 方案。当您的单元测试使用包含具有相同名称的表的多个目录时,它甚至可能会起作用,因为您只需在表名称属性中提供不同的名称。

于 2013-02-16T13:38:33.020 回答
0

设置中有明显错误。连接 URL 必须指向服务器:

<property name="hibernate.connection.url" value="jdbc:hsqldb:hsql://localhost/tsg"/>
于 2012-11-13T19:54:06.360 回答