使用<generator>設置主鍵生成方式(摘抄)

    <generator>是<id>的子元素,該元素的作用是指定主鍵的生成器。它通過一個class屬性指定生成器對應的類,該類必須實現org.hibernate.id.IdentifierGenerator接口。如果需要傳遞參數,需要通過<param>子元素指定。例如:
 <id name="id" column="ID" type="long">
  <generator class="hilo">
   <param name="table">uid_table</param>
   <param name="column">next_hi_value_column</param>
  </generator>
 </id>

    Hibernate提供了很多內置的生成器實現。下面是一些內置生成器的快捷名稱:

(1)assigned算法
    主鍵由外部程序負責生成,無須Hibernate參與,因此需要應用程序在執行save()之前爲對象分配一個標識符。這是<generator>元素沒有指定時的默認生成策略。
    當選擇assigned生成器時,除非有一個version或timestamp屬性,或者你定義了Interceptor.isUnsaved(),否則需要讓Hibernate使用unsaved-value="undefined",強制Hibernate查詢數據庫來確定一個實例是瞬時的(transient)還是託管的(detached)。例:
 <id name="id" column="ID" type="long" unsaved-value="undefined">
  <generator class="assigned"/>
 </id>

(2)hilo算法
    使用hilo(高/低位)算法高效地生成long,short或者int類型的標識符。高/低位算法生成的標識符只在一個特定的數據庫中是唯一的,需要額外的數據庫表或字段提供高位值來源。
    hilo生成器需要一個“特殊”的數據庫表來保存下一個可用的“hi”值。使用該算法是需要通過以下3個參數來指定數據庫中的表信息來保存“hi”值:
    table:保存ID的表名。
    column:保存ID的字段名。
    max_lo:最大編號。
例:
 <id name="id" column="ID" type="long">
  <generator class="hilo">
   <param name="table">hi_value</param>
   <param name="columm">next_value</param>
   <param name="max_lo">100</param>
  </generator>
 </id>

(3)seqhilo算法
    與hilo類似,通過hi/lo算法實現的主鍵生成機制,只是主鍵歷史狀態保存在Sequence中,適用於支持Sequence的數據庫,如Oracle。
    seqhilo生成器使用一個Oracle風格的序列,這要求數據庫支持序列。它需要包括以下兩個參數。
    Sequence:序列名。
    max_lo:最大編號。
例:
 <id name="id" column="ID" type="long">
  <generator class="seqhilo">
   <param name="sequence">hi_value</param>
   <param name="max_lo">100</param>
  </generator>
 </id>

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

(5)identy算法
    identy採用數據庫提供的主鍵生成機制,如DB2、MySQL、Sybase、MS SQL中的主鍵生成機制,這需要這些數據庫內部支持標識字段。
例:
 <id name="id" column="ID" type="long" unsaved-value="0">
  <generator class="identy"/>
 </id>

(6)sequence算法
    sequence採用數據庫提供的Sequnce機制生成機制生成主鍵,如Oracle中的Sequence。對於內部支持序列的數據庫(DB2、Oracle、PostgreSQL、Interbase、McKoi、SAP DB),你可以使用Sequence風格的關鍵字生成。
例:
 <id name="id" column="ID" type="long">
  <generator class="seqence">
   <param name="sequence">user_id_sequence</param>
  </generator>
 </id>
    sequence與seqhilo都使用數據庫的序列,但是不同的是,sequence是使用序列生成的ID,而seqhilo是用序列來保存程序生成的ID,該ID由算法自動生成。

(7)native算法
    由Hibernate根據底層數據庫自行判斷採用identity、hilo和sequence其中一種作爲主鍵生成方式。對於跨平臺開發,native策略會從identity、hilo和sequence中進行選擇,選擇哪一個,這取決於底層數據庫的支持能力。
例:
 <id name="id" column="ID" type="long">
  <generator class="native"/>
 </id>

(8)uuid.hex算法
    由Hibernate基於128位唯一值產生算法UUID生成16進制數值(編碼後以長度32位的字符串表示)作爲主鍵。
    UUID包含:IP地址、JVM的啓動時間(精確到1/4秒)、系統時間和一個計數器值(在JVM中唯一)。在Java代碼中不可能獲得MAC地址或者內在地址,所以這已經是我們在不使用JNI(Java Native Interface,JAVA本地調用)的前提下能做的最好實現了。
例:
 <id name="id" column="ID" type="long">
  <generator class="uuid.hex"/>
 </id>
    一般而言,利用uuid.hex方式生成主鍵將提供最好的性能和數據庫平臺實用性。

(9)uuid.string算法
    與uuid.hex類似,只是生成的主鍵未進行編碼(長度16)。在某些數據庫中可能出現問題,如(PostgreSQL)。
例:
 <id name="id" column="ID" type="long">
  <generator class="uuid.string"/>
 </id>

(10)foreign算法
    使用另外一個相關聯的對象的標識符。通常和<one-to-one>聯合起來使用。
例:
 <id name="id" column="ID" type="long">
  <generator class="foreign"/>
 </id>

(11)select算法
    通過數據庫觸發器選擇一些唯一主鍵的行並返回主鍵盤值來分配一個主鍵。
    例如下例中,定義了一個命名爲socialSecurityNumber的唯一值屬性,它是一個自然鍵(natural key),命名爲ID的代理鍵(surrogate key)的值由觸發器生成。
 <id name="id" column="ID" type="long">
  <generator class="select">
   <param name="key">socialSecurityNumber</param>
  </generator>
 </id>

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

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