【持久層框架-Hibernate系列】-方言

Hibernate底層依然使用SQL語句來執行數據庫操作,雖然所有關係型數據庫都支持使用標準SQL語句,但所有數據庫都對標準SQL進行了一些擴展,所以在語法細節上存在一些差異,因此Hibernate需要根據數據庫來識別這些差異。

Hibernate底層依然使用SQL語句來執行數據庫操作,雖然所有關係型數據庫都支持使用標準SQL語句,但所有數據庫都對標準SQL進行了一些擴展,所以在語法細節上存在一些差異,因此Hibernate需要根據數據庫來識別這些差異。

舉例來說,我們在MySQL數據庫裏進行分頁查詢,只需使用limit關鍵字就可以了;而標準SQL並不支持limit關鍵字,例如Oracle則需要使用行內視圖的方式來進行分頁。同樣的應用程序,當我們在不同數據庫之間遷移時,底層數據庫的訪問細節會發生改變,而Hibernate也爲這種改變做好了準備,現在我們需要做的是:告訴Hibernate應用程序的底層即將使用哪種數據庫——這就是數據庫方言。

一旦我們爲Hibernate設置了合適的數據庫方言,Hibernate將可以自動應付底層數據庫訪問所存在的細節差異。

不同數據庫所應使用的方言如表5.1所示。

表  不同數據庫及其對應方言

關係數據庫

方    言

DB2

org.hibernate.dialect.DB2Dialect

DB2 AS/400

org.hibernate.dialect.DB2400Dialect

DB2 OS390

org.hibernate.dialect.DB2390Dialect

PostgreSQL

org.hibernate.dialect.PostgreSQLDialect

MySQL

org.hibernate.dialect.MySQLDialect

MySQL with InnoDB

org.hibernate.dialect.MySQLInnoDBDialect

MySQL with MyISAM

org.hibernate.dialect.MySQLMyISAMDialect

Oracle(any version)

org.hibernate.dialect.OracleDialect

Oracle 9i

org.hibernate.dialect.Oracle9iDialect

Oracle 10g

org.hibernate.dialect.Oracle10gDialect 

 

 

Sybase

org.hibernate.dialect.SybaseDialect

Sybase Anywhere

org.hibernate.dialect.SybaseAnywhereDialect

Microsoft SQL Server

org.hibernate.dialect.SQLServerDialect

SAP DB

org.hibernate.dialect.SAPDBDialect

Informix

org.hibernate.dialect.InformixDialect

HypersonicSQL

org.hibernate.dialect.HSQLDialect

Ingres

org.hibernate.dialect.IngresDialect

Progress

org.hibernate.dialect.ProgressDialect

Mckoi SQL

org.hibernate.dialect.MckoiDialect

Interbase

org.hibernate.dialect.InterbaseDialect

Pointbase

org.hibernate.dialect.PointbaseDialect

FrontBase

org.hibernate.dialect.FrontbaseDialect

Firebird

org.hibernate.dialect.FirebirdDialect

    如果一個系統可能運行於多種數據庫,或者同時使用多種數據庫,那麼,使用Hibernate將會給你帶來很多的方便,想信很多接觸Hibernate的人都會體會到。Hibernate底層是通過dialect包來對各種數據庫的差異進行抽象的。Dialect類中實現每種數據庫相同的東西,而不同數據庫對應會有該類的一個擴展實現,最終通過DialectFactory來決定創建哪一個類。通常我們都會指定hibernate.dialect屬性,那直接創建該屬性對應的類。如果我們沒有指定該屬性,那麼由Hibernate自己決定選擇合適的方言。在DialectFactory中初始化各種數據庫對應的方言的Map,以數據庫產品名爲key,以方言的包裝對象爲value。Hibernate自動選擇方言時,會通過JDBC的DatabaseMetadata取得數據庫的產品名稱,根據名稱取得對應的方言。DialectFactory中對該Map的初始化的部分代碼如下:
  1. // TODO : this is the stuff it'd be nice to move to a properties file or some other easily user-editable place   
  2.     private static final Map MAPPERS = new HashMap();   
  3.     static {   
  4.         // detectors...   
  5.         MAPPERS.put( "HSQL Database Engine"new VersionInsensitiveMapper( "org.hibernate.dialect.HSQLDialect" ) );   
  6.         MAPPERS.put( "H2"new VersionInsensitiveMapper( "org.hibernate.dialect.H2Dialect" ) );   
  7.         MAPPERS.put( "MySQL"new VersionInsensitiveMapper( "org.hibernate.dialect.MySQLDialect" ) );   
  8.         MAPPERS.put( "PostgreSQL"new VersionInsensitiveMapper( "org.hibernate.dialect.PostgreSQLDialect" ) );   
  9.         MAPPERS.put( "Apache Derby"new VersionInsensitiveMapper( "org.hibernate.dialect.DerbyDialect" ) );   
  10. <SPAN>...</SPAN>  
    原本上,這種自動選擇的方式,會給我們帶來方便,只可惜,從以上的代碼的註釋中可以知道,目前這一部分的初始化是通過硬編碼的,只有在以後的版本纔會移動到配置文件或其他容易用戶編譯的地方,否則,我們可以非常容易的添加我們的配置供Hibernate進行自動選擇。而經常我們所使用的數據庫驅動程序所取到的數據庫產品名稱會跟以上硬編碼的不同,所以最終我們還是得自己配置數據庫方言。

   由於我們的系統中用到了好幾個數據源,經常也是對應不同類型的數據庫,並且數據源都是由容器提供的,在首次部署時經常因爲數據庫類型變了而忘了修改對應的數據庫方言,而出了問題,這給實施人員帶來了很多的不便。不過目前除了對各種數據庫提供與以上硬編碼相同的數據庫產品名稱的驅動程序外,我們就只能自己動手了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章