4

Hibernate 4.3 から Hibernate 5.0.1-Final にアプリケーションを移行していますImplicitNamingStrategyComponentPathImpl。私hibernate.implicit_naming_strategyは Postgres 9.4.4 で使用し、私の会社はhibernate.hbm2ddl.auto = update展開に使用しています (私はそれが悪い習慣であることを知っていますが、それを助けることはできません)。

セッション ファクトリの初期化中に、以下のエラーがスローされます。どうやら、生成されたエイリアスは Postgres には長すぎます。この状況をどのように処理しますか?これを回避するために注釈を割り当てよう@Table(name=..)としましたが、その時点からのすべての関係が台無しになるにつれて悪化しています。

Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Unable to execute schema management to JDBC target [create table public.ReferenceDocumentVersion_ReferenceDocumentSourceFilesStoreDescriptor (ReferenceDocumentVersion_unid uuid not null, sourceFilesStore_filesDescriptorMap_unid uuid not null, filesDescriptorMap_KEY text not null, primary key (ReferenceDocumentVersion_unid, filesDescriptorMap_KEY))]
    at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:59)
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlString(SchemaMigratorImpl.java:371)
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlStrings(SchemaMigratorImpl.java:360)
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.createTable(SchemaMigratorImpl.java:181)
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigrationToTargets(SchemaMigratorImpl.java:134)
    at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:59)
    at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:129)
    at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:97)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:481)
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:802)
    ... 29 more
Caused by: org.postgresql.util.PSQLException: ERROR: relation "referencedocumentversion_referencedocumentsourcefilesstoredescr" already exists
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2182)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1911)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:618)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:454)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:382)
    at org.apache.tomcat.dbcp.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)
    at org.apache.tomcat.dbcp.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at net.bull.javamelody.JdbcWrapper.doExecute(JdbcWrapper.java:404)
    at net.bull.javamelody.JdbcWrapper$StatementInvocationHandler.invoke(JdbcWrapper.java:129)
    at net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler.invoke(JdbcWrapper.java:286)
    at com.sun.proxy.$Proxy93.executeUpdate(Unknown Source)
    at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:56)
    ... 39 more
4

3 に答える 3

4

ImplicitNamingStrategyHibernate が生成した識別子を 64 文字 (Postgres の最大長) に切り詰めるカスタムで状況に対処しました。

以前のバージョンの Hibernate(4.x) でも同じエラーが発生しましたが、無視して SessionFactory の初期化に進みます。ただし、Hibernate 5.x には、そのような場合に SchemaManagementException をスローして中止する新しいブート ストラップ API があります。テスト シナリオの Hibernate ログを参照用に以下に貼り付けます。

休止状態 4.X

INFO: HHH000396: Updating schema
Oct 04, 2015 1:38:00 PM org.hibernate.tool.hbm2ddl.DatabaseMetadata getTableMetadata
INFO: HHH000262: Table not found: ReferenceDocumentVersionEntityWithAReallyReallyReallyLongNameBeyondPostGres
Oct 04, 2015 1:38:00 PM org.hibernate.tool.hbm2ddl.DatabaseMetadata getTableMetadata
INFO: HHH000262: Table not found: ReferenceDocumentVersionEntityWithAReallyReallyReallyLongNameBeyondPostGres
Oct 04, 2015 1:38:00 PM org.hibernate.tool.hbm2ddl.DatabaseMetadata getTableMetadata
INFO: HHH000262: Table not found: ReferenceDocumentVersionEntityWithAReallyReallyReallyLongNameBeyondPostGres
Oct 04, 2015 1:38:00 PM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
ERROR: HHH000388: Unsuccessful: create table ReferenceDocumentVersionEntityWithAReallyReallyReallyLongNameBeyondPostGres (unid uuid not null, path text, primary key (unid))
Oct 04, 2015 1:38:00 PM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
ERROR: ERROR: relation "referencedocumentversionentitywithareallyreallyreallylongnamebe" already exists
Oct 04, 2015 1:38:00 PM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000232: Schema update complete

休止状態 5.0.2.Final

Oct 04, 2015 1:39:16 PM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000228: Running hbm2ddl schema update
Oct 04, 2015 1:39:16 PM org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl processGetTableResults
INFO: HHH000262: Table not found: ReferenceDocumentVersionEntityWithAReallyReallyReallyLongNameBeyondPostGres
Oct 04, 2015 1:39:16 PM org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl processGetTableResults
INFO: HHH000262: Table not found: ReferenceDocumentVersionEntityWithAReallyReallyReallyLongNameBeyondPostGres
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.813 sec <<< FAILURE!
testApp(org.foobar.AppTest)  Time elapsed: 0.788 sec  <<< ERROR!
javax.persistence.PersistenceException: [PersistenceUnit: org.foobar.persistence.default] Unable to build Hibernate SessionFactory
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:877)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:805)
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
    at org.foobar.AppTest.testApp(AppTest.java:18)

解決

  • カスタム ImplicitNamingStrategy

    package org.foobar.persistence;
    import org.hibernate.boot.model.naming.Identifier;
    import org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl;
    import org.hibernate.boot.spi.MetadataBuildingContext;
    
    public class PGConstrainedImplicitNamingStrategy extends ImplicitNamingStrategyComponentPathImpl {
    private static final int POSTGRES_IDENTIFIER_MAXLENGTH = 63;
    public static final PGConstrainedImplicitNamingStrategy INSTANCE = new PGConstrainedImplicitNamingStrategy();
    
    public PGConstrainedImplicitNamingStrategy() {
    
    }
    
    @Override
    protected Identifier toIdentifier(String stringForm, MetadataBuildingContext buildingContext) {
        return buildingContext.getMetadataCollector()
                .getDatabase()
                .getJdbcEnvironment()
                .getIdentifierHelper()
                .toIdentifier( stringForm.substring( 0, Math.min( POSTGRES_IDENTIFIER_MAXLENGTH, stringForm.length() ) ) );
    
    }}
    
  • persistence.xml

    <properties>
        <property name="hibernate.implicit_naming_strategy" value="org.foobar.persistence.PGConstrainedImplicitNamingStrategy"/>
    </properties>
    

これはスケーラブルなソリューションではありませんが、ショーを継続するのに役立ちます。恒久的な解決策は、休止状態が非常に長い識別子を生成しないように、明示的に識別子を提供することです。- maaartinusによって書かれた回答を参照してください

于 2015-10-05T07:04:23.380 に答える
3

このリンクの Hibernate Documentation の移行ガイドに従ってみてください

https://github.com/hibernate/hibernate-orm/blob/5.0/migration-guide.adoc

于 2015-09-30T15:15:29.000 に答える
2

OPのソリューションは衝突につながる可能性があります(そのため、彼はそれをスケーラブルではないと呼んでいますよね?)。すべての識別子を明示的に提供することは、私にはひどい考えのように思えます。次のいずれかをお勧めします

  • Map<String, String>長すぎる名前をすべて短い名前にマッピングする
  • 長すぎる名前をすべて短縮し、切り取った部分のハッシュから生成された文字POSTGRES_IDENTIFIER_MAXLENGTH - Nを追加するため、衝突の可能性が最小限に抑えられますN
  • のような識別子省略関数を使用し、処理される前にそれを識別子に適用して、代わりに{"Reference" -> "Ref", "Document" -> "Doc", ...}を取得します。RefDocVersion_RefDocSourceFileDescr...referencedocumentversion_referencedocumentsourcefilesstoredescr...
  • コード自体で省略名を使用することを検討してください。これは、理解できないナンセンスにつながりやすいため、しばしば反対されますが、私見では、正しく使用すると読みやすさが向上します (2、3 の略語のみを使用し、それらを体系的に使用します。それらのリストを提供してください)。
于 2016-05-17T02:57:13.180 に答える