インメモリ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
。
この問題の原因と解決方法を誰もが知っていますか?
これらのエラーは無視できます。 create-drop
とインメモリデータベースの組み合わせは、ドロップしようとするすべてのデータベースオブジェクトに対してこれらを生成します。削除するデータベースオブジェクトがないため、DROPステートメントは空のデータベースに対して実行されます。
また、通常のパーマネントデータベースでは、DROPステートメントを実行する前にHibernateがデータベースにオブジェクトを追加したり、新しいものにしたりしないため、このようなエラーが発生します。
与えられた他のソリューションとは対照的に、このソリューションは私のために働いた。明らかに走行距離は異なります。
これは私の正確なエラーでした:
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;
}
}
上記のソリューション@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
dbCreate="update"
、およびエラーはすぐになくなります。
迷惑なエラーメッセージは、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;
};
}
Spring
に簡単なログインウィンドウを作成しようとしたときに、同じ問題に直面しました。 user
とrole
の2つのテーブルがあり、両方とも主キーid
タイプのBIGINT
でした。マッピングしたもの(Many-to-Many
)別のテーブルにuser_roles
2列のuser_id
およびrole_id
外部キーとして。
問題はrole_id
列のuser_roles
テーブル、int
タイプであり、role
への外部キーと互換性がありません。タイプがBIGINT
に変更されたとき、エラーは修正されました。