hibernate @indexアノテーションを使用してDBのインデックスを作成します
-
30-09-2019 - |
質問
私はプロジェクトに注釈駆動型の冬眠能力を持っています。
次に、列を介してインデックスを作成したいと思います。私の現在の列定義はです
@NotNull
@Column(name = "hash")
private String hash;
そして、私は追加します @Index
ここで注釈。
@NotNull
@Column(name = "hash")
@Index(name="hashIndex")
private String hash;
次に、テーブルをドロップして、Tomcatサーバーを再起動します。サーバーがインスタンス化された後、テーブルが作成されますが、次のクエリで新しいインデックスが表示されません。
SHOW INDEX FROM tableName
新しいインデックスを使用してテーブルを構築することが期待されています。 MySQLでInnoDBを使用しています。
解決
興味深いことに、私が使用していた冬眠構成で hibernate.hbm2ddl.auto=update
.
これは、既存のデータベースを変更します。私は手動でテーブルを落としていました tableName
Tomcatの再起動とテーブルは構築されていましたが、インデックスは作成されていませんでした。
しかし、私は作った hibernate.hbm2ddl.auto=create
WebAppのインスタンス化ごとにデータベースを再作成すると、すべてのデータベースがドロップされ、再構築され、ええ - 新しいインデックスが作成されました!
他のヒント
スキーマアップデートでのインデックス作成は、スキーマエクスポートで使用されている命名と矛盾しているように思われるため、Hibernateで意図的に無効にされました。
これは、クラスで見つけることができるコメントコードです org.hibernate.cfg.Configuration
.
//broken, 'cos we don't generate these with names in SchemaExport
subIter = table.getIndexIterator();
while ( subIter.hasNext() ) {
Index index = (Index) subIter.next();
if ( !index.isForeignKey() || !dialect.hasImplicitIndexForForeignKey() ) {
if ( tableInfo==null || tableInfo.getIndexMetadata( index.getFilterName() ) == null ) {
script.add( index.sqlCreateString(dialect, mapping) );
}
}
}
//broken, 'cos we don't generate these with names in SchemaExport
subIter = table.getUniqueKeyIterator();
while ( subIter.hasNext() ) {
UniqueKey uk = (UniqueKey) subIter.next();
if ( tableInfo==null || tableInfo.getIndexMetadata( uk.getFilterName() ) == null ) {
script.add( uk.sqlCreateString(dialect, mapping) );
}
}
通常、私はそのコメントを削除し、hibernate.jarを再コンパイルし、少なくともOracle DBで問題なくスキーマアップデートにインデックスを作成します。
Hibernateの最近のバージョンでは、最初の部分(テーブルインデックス)に関するコメントも公式バージョンで削除されましたが、2番目のバージョン(一意のキーを実装するインデックス)にまだコメントされています。での議論を参照してください http://opensource.atlassian.com/projects/hibernate/browse/hhh-1012
より良いDB設計とは、スキーマがデータ自体とは異なるユーザーが所有することを意味します。したがって、私は設定します hibernate.hbm2ddl.auto=none
したがって、冬眠の開始時に失敗はありません。代わりにSchemaprinterを使用します。出力は、お気に入りのSQLツールを介して実行して、必要に応じてスキーマを再現できます。
import java.io.IOException;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.tool.hbm2ddl.SchemaExport;
public class SchemaPrinter {
public static void main(String[] args) throws IOException {
Configuration cfg = new AnnotationConfiguration()
.addAnnotatedClass(MyClass1.class)
.addAnnotatedClass(MyClass2.class)
.setProperty(Environment.USER, "user")
.setProperty(Environment.PASS, "password")
.setProperty(Environment.URL, "jdbc:sybase:jndi:file://sql.ini?mydb")
.setProperty(Environment.DIALECT, "org.hibernate.dialect.SybaseASE15Dialect")
.setProperty(Environment.DRIVER, "com.sybase.jdbc4.jdbc.SybDriver")
.setProperty(Environment.HBM2DDL_AUTO, "none")
SchemaExport exp = new SchemaExport(cfg);
exp.setOutputFile("schema.ddl");
exp.create(true, false);
}
}
Hibernate 3.5.6で使用 <property name="hibernate.hbm2ddl.auto">update</property
>インデックスが作成されます。したがって、適切な答えはアップグレードすることです。しかし、私はこの質問に出くわした私のような人々のためにこの答えを残しています。