簡體   English   中英

Hibernate:模式驗證:缺少表 - 區分大小寫 Mysql 模式標識符變為大寫

[英]Hibernate: Schema-validation: missing table - case-sensitive Mysql schema identifier turned upper-case

(上下文 - 將工作 Java 服務器應用程序從 Spring/Hibernate 3 遷移到 5)

服務器啟動后,Hibernate 驗證失敗並顯示“ Schema-validation: missing table ”。 表格存在(應用程序正在使用 Hibernate 3)

原因是查詢 [1] 從 DB informationSchema 中獲取所有表。 數據庫名稱為“myApp”,但查詢“WHERE (TABLE_SCHEMA = 'MYAPP')”。 這會導致空結果集和“缺失表”。

原因是“unquotedCaseStrategy”[2] (IdentifierCaseStrategy.UPPER) 的初始值在“applyIdentifierCasing”方法中保持不變,其中所有 metaData.storesLowerCaseIdentifiers()、metaData.storesUpperCaseIdentifiers()、metaData.storesMixedCaseIdentifiers() 返回 FALSE ,因為在 MariaDbDatabaseMetaData#connection#getLowercaseTableNames() [4] 方法中調用的 select @@lower_case_table_names 返回“0”。 這是 Unix 系統的默認值,正如 JavaDoc [5] 所述,所有表名和別名以及數據庫名稱都以區分大小寫的方式進行比較。

  • Hibernate = 5.6.7
  • Java = jdk1.8.0_241
  • AppServer = wildfly-18.0.1.Final
  • 數據庫 = MariaDb 10.1
  • 數據庫驅動程序 = mariadb-java-client-2.2.6.jar

[1]

SELECT TABLE_SCHEMA TABLE_CAT, NULL TABLE_SCHEM, TABLE_NAME, IF(TABLE_TYPE='BASE TABLE', 'TABLE', TABLE_TYPE) as TABLE_TYPE, TABLE_COMMENT REMARKS, NULL TYPE_CAT, NULL TYPE_SCHEM, NULL TYPE_NAME, NULL SELF_REFERENCING_COL_NAME, NULL REF_GENERATION FROM INFORMATION_SCHEMA.TABLES WHERE ( TABLE_SCHEMA = 'MYAPP') AND (TABLE_NAME LIKE '%') AND TABLE_TYPE IN ('BASE TABLE','VIEW') 按 TABLE_TYPE、TABLE_SCHEMA、TABLE_NAME 排序;

[2] org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder#unquotedCaseStrategy

[3] org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder#applyIdentifierCasing

[4] org.mariadb.jdbc.MariaDbConnection#getLowercaseTableNames

[5] getLowercaseTableNames Javadoc:- 表是否區分大小寫。 默認值:0 (Unix)、1 (Windows)、2 (Mac OS X)。 如果設置為 0(基於 Unix 的系統的默認值),表名和別名以及數據庫名稱將以區分大小寫的方式進行比較。 如果設置為 1(Windows 上的默認值),名稱將以小寫形式存儲並且不以區分大小寫的方式進行比較。 如果設置為 2(Mac OS X 上的默認值),名稱按聲明存儲,但以小寫形式進行比較。

在我看來,applyIdentifierCasing 方法邏輯中存在錯誤,unquotedCaseStrategy 策略 [2] 的默認值(初始值)應該是 IdentifierCaseStrategy.MIXED。

變通方法:擴展org.hibernate.dialect@Override buildIdentifierHelper()方法中的一種方言,直接返回 IdentifierHelper 實例(調用 builder.build(); 而不是 super.buildIdentifierHelper(...) 會覆蓋配置)。

public class MySQL5InnoDBDialectEx extends MySQL55Dialect {

    public MySQL5InnoDBDialectEx() {
        super();
        registerColumnType(Types.BIT, "tinyint(1)");
    }

    @Override
    public IdentifierHelper buildIdentifierHelper(IdentifierHelperBuilder builder, DatabaseMetaData dbMetaData) throws SQLException {

        // Copied from org.hibernate.dialect.Dialect#buildIdentifierHelper..
        builder.applyReservedWords(dbMetaData);
        builder.applyReservedWords(AnsiSqlKeywords.INSTANCE.sql2003());

        builder.setUnquotedCaseStrategy(IdentifierCaseStrategy.MIXED);
        builder.setQuotedCaseStrategy(IdentifierCaseStrategy.MIXED);

        // DO NOT USE   >>return super.buildIdentifierHelper( builder, dbMetaData );<<
        // as is normally done in the superClasses, because it overwrites the Quoted/UnquotedCaseStrategy  (that is a bug..)
        return builder.build();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM