3

私は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 1 つ (これは動作しません) があります。

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 データベースのテスト構成 (すべての hibernate クラス マッピングと共に) を用意します。
  • 単体テスト用に HSQL db を開始し、プロジェクトのスキーマを使用してメモリ内データベースを作成します (クラス要素の下の persistence.xml で説明されています)。
  • エンティティ オブジェクトを作成し、テスト時にテスト データベースに追加して、統合テストにデータベースを使用できるようにします。

この PersistenceException を乗り越えることができません!

アップデート

OK、それで、テスト ケースのセットアップで明示的な HSQL サーバーをセットアップする必要がないことに気付きましpersistence-unitpersistence.xml。また、マッピング クラスで使用されるカタログと一致するように、CATALOG を ALTER しようとしました。テスト ケースのセットアップは次のようになります。

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 では、データベースごとに 1 つのカタログしかありません。カタログの名前は PUBLIC です。ALTER CATALOG RENAME TO ステートメントを使用して、カタログの名前を変更できます。すべてのスキーマはこのカタログに属します。カタログ名は、データベースのファイル名とは関係ありません。

私が読んだように、HSQL がデータベースを作成するPUBLICと、そのデータベース内で名前が付けられたカタログと、そのカタログ内で名前が付けられたスキーマが作成さPUBLICれます。HSQL データベースごとに存在できるカタログは 1 つだけです。その単一のカタログ内に複数のスキーマが存在する場合があります。

あなたが得ているエラーは、実際にはcatalog = "tsg"マッピングで指定しようとしたことが原因です。そのカタログは存在しません。HSQL データベースにはカタログを 1 つしか含めることができないため、そのPUBLICカタログの名前を変更するTSG(またはマッピングを変更する) 必要があります。

于 2012-11-13T21:30:14.700 に答える
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 で以下を更新します (hbm2ddl.auto の代わりに hibernate.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 に答える