web-dev-qa-db-ja.com

失敗:Hibernate / JPA / HSQLDBスタンドアロンのテーブルXXXドロップ制約YYYの変更

インメモリHSQL DBを使用してHibernate/JPAの例を実行しようとしています。表示されるエラーメッセージは次のとおりです。

13:54:21,427 ERROR SchemaExport:425 - HHH000389: Unsuccessful: alter table ReferringItem_map drop constraint FK5D4A98E0361647B8
13:54:21,427 ERROR SchemaExport:426 - user lacks privilege or object not found: PUBLIC.REFERRINGITEM_MAP
13:54:21,427 ERROR SchemaExport:425 - HHH000389: Unsuccessful: alter table ReferringItem_myCollection drop constraint FK75BA3266361647B8
13:54:21,427 ERROR SchemaExport:426 - user lacks privilege or object not found: PUBLIC.REFERRINGITEM_MYCOLLECTION
13:54:21,428 ERROR SchemaExport:425 - HHH000389: Unsuccessful: alter table ReferringItem_myList drop constraint FK6D37AA66361647B8
13:54:21,428 ERROR SchemaExport:426 - user lacks privilege or object not found: PUBLIC.REFERRINGITEM_MYLIST
13:54:21,428 ERROR SchemaExport:425 - HHH000389: Unsuccessful: alter table ReferringItem_mySet drop constraint FK3512699A361647B8
13:54:21,429 ERROR SchemaExport:426 - user lacks privilege or object not found: PUBLIC.REFERRINGITEM_MYSET

対応するクラスは次のとおりです。

@Entity
public class ReferringItem implements Serializable {

    @Id
    private long id;

    @ElementCollection
    private Collection<AnEmbeddable> myCollection
        = new ArrayList<AnEmbeddable>();

    @ElementCollection(fetch=FetchType.EAGER)
    private Set<Long> mySet = new HashSet<Long>();

    @ElementCollection(targetClass=String.class)
    private List myList = new ArrayList();

    @ElementCollection
    private Map<String,AnEmbeddable> map
        = new HashMap<String,AnEmbeddable>();

    public ReferringItem() { }

    // Setters & Getters

}

埋め込み可能なものは次のとおりです。

@Embeddable
public class AnEmbeddable implements Serializable {

    private String s;

    public AnEmbeddable() { }

    public String getS() {
        return s;
    }

    public void setS(String s) {
        this.s = s;
    }

}

僕の persistence.xml

<persistence xmlns="http://Java.Sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://Java.Sun.com/xml/ns/persistence http://Java.Sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">

    <persistence-unit name="JPA" transaction-type="RESOURCE_LOCAL">

        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <class>com.jverstry.jpa.AuthorizedTypes.AuthorizedTypes</class>
        <class>com.jverstry.jpa.AuthorizedTypes.OtherEntity</class>
        <class>com.jverstry.jpa.AuthorizedTypes.SomeEmbeddable</class>

        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:testdb"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
        </properties>

    </persistence-unit>

</persistence>

私はHibernateにいます4.1.5.FinalおよびHSQLDB 2.2.8

この問題の原因と解決方法を誰もが知っていますか?

40

これらのエラーは無視できます。 create-dropとインメモリデータベースの組み合わせは、ドロップしようとするすべてのデータベースオブジェクトに対してこれらを生成します。削除するデータベースオブジェクトがないため、DROPステートメントは空のデータベースに対して実行されます。

また、通常のパーマネントデータベースでは、DROPステートメントを実行する前にHibernateがデータベースにオブジェクトを追加したり、新しいものにしたりしないため、このようなエラーが発生します。

55
Mikko Maunu

与えられた他のソリューションとは対照的に、このソリューションは私のために働いた。明らかに走行距離は異なります。

これは私の正確なエラーでした:

HHH000389: Unsuccessful: alter table ... drop constraint FK_g1uebn6mqk9qiaw45vnacmyo2 if exists
Table "..." not found; SQL statement: ...

これは私の解決策であり、H2方言をオーバーライドします。

package com.totaalsoftware.incidentmanager;

import org.hibernate.dialect.H2Dialect;

/**
 * Workaround.
 * 
 * @see https://hibernate.atlassian.net/browse/hhh-7002
 * 
 */
public class ImprovedH2Dialect extends H2Dialect {
    @Override
    public String getDropSequenceString(String sequenceName) {
        // Adding the "if exists" clause to avoid warnings
        return "drop sequence if exists " + sequenceName;
    }

    @Override
    public boolean dropConstraints() {
        // We don't need to drop constraints before dropping tables, that just
        // leads to error messages about missing tables when we don't have a
        // schema in the database
        return false;
    }
}
28
Sander Verhagen

上記のソリューション@SanderはMYSQLでも機能します。以下のように、MySQL5InnoDBDialectを拡張するだけです。

import org.hibernate.dialect.MySQL5InnoDBDialect;

public class ImprovedMySQLDialect extends MySQL5InnoDBDialect {
    @Override
    public String getDropSequenceString(String sequenceName) {
        // Adding the "if exists" clause to avoid warnings
        return "drop sequence if exists " + sequenceName;
    }

    @Override
    public boolean dropConstraints() {
        // We don't need to drop constraints before dropping tables, that just leads to error
        // messages about missing tables when we don't have a schema in the database
        return false;
    }
}

次に、データソースファイルで次の行を変更します。

dialect = org.hibernate.dialect.MySQL5InnoDBDialect

dialect = my.package.name.ImprovedMySQLDialect
12
Emmanuel John

dbCreate="update"、およびエラーはすぐになくなります。

参照: https://stackoverflow.com/a/31257468/715608

12
10GritSandpaper

迷惑なエラーメッセージは、HSQLDBおよびhbm2ddl.auto = create-dropでインメモリデータベースを使用するすべてのテストの開始時に、より不快なスタックトレースになりました。

HSQLDBバグレポート への応答は、DROP CONSTRAINT IF EXISTSではなくDROP TABLE ... CASCADEの使用を提案しました。残念ながら、ドロップテーブルのHSQLDB構文はDROP TABLE <table> [IF EXISTS] [RESTRICT | CASCADE]; Hibernate Dialectは、最後のIF EXISTS節の後にCASCADEを指定するための方言の簡単なメカニズムを提供しません。この制限について バグ を書きました。

ただし、次のようにカスタムの方言を作成することで、この問題を克服できました。

public class HsqlDialectReplacement extends HSQLDialect {

  @Override
  public String getDropTableString( String tableName ) {
    // Append CASCADE to formatted DROP TABLE string
    final String superDrop = super.getDropTableString( tableName );
    return superDrop + " cascade";
  }

  @Override
  public boolean dropConstraints() {
      // Do not explicitly drop constraints, use DROP TABLE ... CASCADE
      return false;
  }

  @Override
  public Exporter<Table> getTableExporter() {
    // Must override TableExporter because it also formulates DROP TABLE strings
    synchronized( this ) {
      if( null == overrideExporter ) {
        overrideExporter = new HsqlExporter( super.getTableExporter() );
      }
    }

    return overrideExporter;
  }

  private Exporter<Table> overrideExporter = null;

  private static class HsqlExporter implements Exporter<Table> {
    HsqlExporter( Exporter<Table> impl ) {
      this.impl = impl;
    }

    @Override
    public String[] getSqlCreateStrings( Table exportable, Metadata metadata ) {
      return impl.getSqlCreateStrings( exportable, metadata );
    }

    @Override
    public String[] getSqlDropStrings( Table exportable, Metadata metadata ) {
      final String[] implDrop = impl.getSqlDropStrings( exportable, metadata );
      final String[] dropStrings = new String[implDrop.length];
      for( int i=0; i<implDrop.length; ++i ) {
        dropStrings[i] = implDrop[i] + " cascade";
      }
      return dropStrings;
    }

    private final Exporter<Table> impl;
  };
}
2
wbdarby

Springに簡単なログインウィンドウを作成しようとしたときに、同じ問題に直面しました。 userroleの2つのテーブルがあり、両方とも主キーidタイプのBIGINTでした。マッピングしたもの(Many-to-Many)別のテーブルにuser_roles 2列のuser_idおよびrole_id外部キーとして。

問題はrole_id列のuser_rolesテーブル、intタイプであり、roleへの外部キーと互換性がありません。タイプがBIGINTに変更されたとき、エラーは修正されました。

0
Arun Sudhakaran