hibernate 主鍵生成方式

Key Generator
主鍵產生器
可選項說明:
1) assigned
主鍵由外部程序負責生成,無需Hibernate參與。

2) hilo
通過hi/lo 算法實現的主鍵生成機制,需要額外的數據庫表保存主
鍵生成歷史狀態。

3) seqhilo
與hilo 類似,通過hi/lo 算法實現的主鍵生成機制,只是主鍵歷史
狀態保存在Sequence中,適用於支持Sequence的數據庫,如Oracle。

4) increment
主鍵按數值順序遞增。此方式的實現機制爲在當前應用實例中維持
一個變量,以保存着當前的最大值,之後每次需要生成主鍵的時候
將此值加1作爲主鍵。
這種方式可能產生的問題是:如果當前有多個實例訪問同一個數據
庫,那麼由於各個實例各自維護主鍵狀態,不同實例可能生成同樣
的主鍵,從而造成主鍵重複異常。因此,如果同一數據庫有多個實
例訪問,此方式必須避免使用。

5) identity
採用數據庫提供的主鍵生成機制。如DB2、SQL Server、MySQL
中的主鍵生成機制。

6) sequence
採用數據庫提供的sequence 機制生成主鍵。如Oralce 中的
Sequence。

7) native
由Hibernate根據底層數據庫自行判斷採用identity、hilo、sequence
其中一種作爲主鍵生成方式。

8) uuid.hex
由Hibernate基於128 位唯一值產生算法生成16 進制數值(編碼後
以長度32 的字符串表示)作爲主鍵。

9) uuid.string
與uuid.hex 類似,只是生成的主鍵未進行編碼(長度16)。在某些
數據庫中可能出現問題(如PostgreSQL)。

10) foreign
使用外部表的字段作爲主鍵。
一般而言,利用uuid.hex方式生成主鍵將提供最好的性能和數據庫平臺適
應性。

另外由於常用的數據庫,如Oracle、DB2、SQLServer、MySql 等,都提
供了易用的主鍵生成機制(Auto-Increase 字段或者Sequence)。我們可以在數
據庫提供的主鍵生成機制上,採用generator-class=native的主鍵生成方式。
不過值得注意的是,一些數據庫提供的主鍵生成機制在效率上未必最佳,
大量併發insert數據時可能會引起表之間的互鎖。
數據庫提供的主鍵生成機制,往往是通過在一個內部表中保存當前主鍵狀
態(如對於自增型主鍵而言,此內部表中就維護着當前的最大值和遞增量),
之後每次插入數據會讀取這個最大值,然後加上遞增量作爲新記錄的主鍵,之
後再把這個新的最大值更新回內部表中,這樣,一次Insert操作可能導致數據
庫內部多次表讀寫操作,同時伴隨的還有數據的加鎖解鎖操作,這對性能產生
了較大影響。
因此,對於併發Insert要求較高的系統,推薦採用uuid.hex 作爲主鍵生成
機制。

------------------------------------------------------------------------

其次:

關於ID配置
      被映射的類必須聲明對應數據庫表主鍵字段。大多數類有一個JavaBeans風格的屬性,爲每一個實例包含唯一的標識。<id> 元素定義了該屬性到數據庫表主鍵字段的映射。

<id
        name="propertyName"                      
        type="typename"                          
        column="column_name"                     
        unsaved-value="any|none|null|id_value"   
        access="field|property|ClassName">       
        <generator class="generatorClass"/>
</id>
name (可選): 標識屬性的名字。

type (可選): 標識Hibernate類型的名字。

column (可選 - 默認爲屬性名): 主鍵字段的名字。

unsaved-value (可選 - 默認爲null): 一個特定的標識屬性值,用來標誌該實例是剛剛創建的,尚未保存。這可以把這種實例和從以前的session中裝載過(可能又做過修改--譯者注)但未再次持久化的實例區分開來。

access (可選 - 默認爲property): Hibernate用來訪問屬性值的策略。

如果 name屬性不存在,會認爲這個類沒有標識屬性。

unsaved-value 屬性很重要!如果你的類的標識屬性不是默認爲null的,你應該指定正確的默認值。

還有一個另外的<composite-id>聲明可以訪問舊式的多主鍵數據。我們強烈不鼓勵使用這種方式。

1. generator
必須聲明的<generator>子元素是一個Java類的名字,用來爲該持久化類的實例生成唯一的標識。如果這個生成器實例需要某些配置值或者初始化參數,用<param>元素來傳遞。

<id name="id" type="long" column="uid" unsaved-value="0">
        <generator class="net.sf.hibernate.id.TableHiLoGenerator">
                <param name="table">uid_table</param>
                <param name="column">next_hi_value_column</param>
        </generator>
</id>
所有的生成器都實現net.sf.hibernate.id.IdentifierGenerator接口。這是一個非常簡單的接口;某些應用程序可以選擇提供他們自己特定的實現。當然,Hibernate提供了很多內置的實現。下面是一些內置生成器的快捷名字:

increment(遞增)
用於爲long, short或者int類型生成唯一標識。只有在沒有其他進程往同一張表中插入數據時才能使用。 在集羣下不要使用。

identity
對DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的內置標識字段提供支持。返回的標識符是long, short 或者int類型的。

sequence (序列)
在DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence),而在Interbase中使用生成器(generator)。返回的標識符是long, short或者 int類型的。

hilo (高低位)
使用一個高/低位算法來高效的生成long, short或者 int類型的標識符。給定一個表和字段(默認分別是是hibernate_unique_key 和next)作爲高位值得來源。高/低位算法生成的標識符只在一個特定的數據庫中是唯一的。在使用JTA獲得的連接或者用戶自行提供的連接中,不要使用這 種生成器。

seqhilo(使用序列的高低位)
使用一個高/低位算法來高效的生成long, short或者 int類型的標識符,給定一個數據庫序列(sequence)的名字。

uuid.hex
用一個128-bit的UUID算法生成字符串類型的標識符。在一個網絡中唯一(使用了IP地址)。UUID被編碼爲一個32位16進制數字的字符串。

uuid.string
使用同樣的UUID算法。UUID被編碼爲一個16個字符長的任意ASCII字符組成的字符串。不能使用在PostgreSQL數據庫中

native(本地)
根據底層數據庫的能力選擇identity, sequence 或者hilo中的一個。

assigned(程序設置)
讓應用程序在save()之前爲對象分配一個標示符。

foreign(外部引用)
使用另外一個相關聯的對象的標識符。和<one-to-one>聯合一起使用。


2. 高/低位算法(Hi/Lo Algorithm)
hilo 和 seqhilo生成器給出了兩種hi/lo算法的實現,這是一種很令人滿意的標識符生成算法。第一種實現需要一個“特殊”的數據庫表來保存下一個可用的“hi”值。第二種實現使用一個Oracle風格的序列(在被支持的情況下)。

<id name="id" type="long" column="cat_id">
        <generator class="hilo">
                <param name="table">hi_value</param>
                <param name="column">next_value</param>
                <param name="max_lo">100</param>
        </generator>
</id>
<id name="id" type="long" column="cat_id">
        <generator class="seqhilo">
                <param name="sequence">hi_value</param>
                <param name="max_lo">100</param>
        </generator>
</id>
很不幸,你在爲Hibernate自行提供Connection,或者Hibernate使用JTA獲取應用服務器的數據源連接的時候無法使用hilo 。Hibernate必須能夠在一個新的事務中得到一個"hi"值。在EJB環境中實現hi/lo算法的標準方法是使用一個無狀態的session bean。

3. UUID算法(UUID Algorithm )
UUID包含:IP地址,JVM的啓動時間(精確到1/4秒),系統時間和一個計數器值(在JVM中唯一)。在Java代碼中不可能獲得MAC地址或者內存地址,所以這已經是我們在不使用JNI的前提下的能做的最好實現了。

不要試圖在PostgreSQL中使用uuid.string。

4. 標識字段和序列(Identity Columns and Sequences)
對於內部支持標識字段的數據庫(DB2,MySQL,Sybase,MS SQL),你可以使用identity關鍵字生成。對於內部支持序列的數據庫(DB2,Oracle, PostgreSQL, Interbase, McKoi,SAP DB),你可以使用sequence風格的關鍵字生成。這兩種方式對於插入一個新的對象都需要兩次SQL查詢。

<id name="id" type="long" column="uid">
        <generator class="sequence">
                <param name="sequence">uid_sequence</param>
        </generator>
</id>
<id name="id" type="long" column="uid" unsaved-value="0">
        <generator class="identity"/>
</id>
      對於跨平臺開發,native策略會從identity, sequence 和hilo中進行選擇,取決於底層數據庫的支持能力。

下面再給個簡單例子:

<id name="id" type="long" column="uid">
    <generator class="sequence">
        <param name="sequence">uid_sequence</param>
    </genarator>
</id>

注意:

<generator class=""> 裏面可以選啊!推薦Oracle用sequence,seqhilo

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