作爲一個成熟的ORM框架,Hibernate對不同的數據庫的支持可以說非常完美,但是在生成數據庫的過程中還是會遇到各種各樣的問題,今天在做數據表映射的時候,發現無法生成數據表,具體的開發環境如下:
- Hibernate 5.2.3.Final
- MySQL Windows 5.5.16
- MySQL connector 5.1.39
發現這個問題之後,梳理一下思路,從以下幾個方面查找問題:
首先查看自己的代碼寫的有沒有問題,啓動Hibernate的代碼如下:
Configuration config = new Configuration().configure(); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder(bsr).applySettings(config.getProperties()).build(); SessionFactory sessionFactory = config.buildSessionFactory(serviceRegistry);
這是基本的Hibernate啓動代碼,非常簡單,沒有任何問題。
查看連接MySQL數據庫的配置,包括但不限於如下:
- 用戶名和密碼是否正確
- 主機和端口是否正確
- 方言dialect是否正確
之後查看MySQL 服務器的問題,包括但不限於下面:
服務器是否開啓
用戶是否有權限執行相關的操作
數據庫服務器的是否已經到最大連接數,默認是100,查詢如下:
SHOW VARIABLES LIKE 'max_connections'
但是經過檢查上面各個方面,發現沒有任何問題,每當到這個時候時候我都開始懷疑人生,甚至是懷疑數據庫本身是不是有bug。既然和單獨一方面沒有關係,那麼是程序和數據庫的連接關係上出了問題,那就是MySQL的驅動問題,換了一個最新版本的數據庫驅動,MySQL Connector 6.0.6,結果發現果然是會玩,竟然連MySQL的驅動類都改了,該版本的驅動名稱是com.mysql.cj.jdbc.Driver
, 但是改完之後並沒有神馬用,此時身心俱疲,腦子開始胡思亂想,是不是連接數據庫的驅動或者是方言和具體的存儲引擎有關,因爲之前看過姜承堯寫的《InnoDB存儲引擎》這本書,死馬當活馬醫,查了一下,真的有org.hibernate.dialect.MySQL5InnoDBDialect
這個方言,之前一直使用org.hibernate.dialect.MySQL5Dialect
,MySQL5InnoDBDialect
是繼承自MySQL5Dialect
,源碼如下:
public class MySQL5InnoDBDialect extends MySQL5Dialect {
@Override
public boolean supportsCascadeDelete() {
return true;
}
@Override
public String getTableTypeString() {
return " ENGINE=InnoDB";
}
@Override
public boolean hasSelfReferentialForeignKeyBug() {
return true;
}
}
結果發現問題解決了!!!這可以確定是存儲引擎的問題了,使用org.hibernate.dialect.MySQL5InnoDBDialect
方言會在建表的DDL語句後面加上ENGINE=InnoDB
,從源碼上也能看出來,而org.hibernate.dialect.MySQL5Dialect是直接使用Dialect中的getTableTypeString(),什麼都不加!!遇到這種問題還是直接去官方文檔中找答案吧,解釋如下:
Dialect | Remarks |
---|---|
MySQL5 | Support for the MySQL database, version 5.x |
MySQL5InnoDB | Support for the MySQL database, version 5.x preferring the InnoDB storage engine whenexporting tables. |
MySQL57InnoDB | Support for the MySQL database, version 5.7 preferring the InnoDB storage engine whenexporting tables. May work with newer versions |
問題完美解決!!之前想MySQL的存儲引擎是插件式的,感覺很厲害,但是代價是兼容性問題要考慮全面一些。
最後要吐槽這一下Hibernate,既然有這種問題爲什麼一點錯誤提示都沒有?好歹也告訴我是哪裏錯了呀!