2、increment
由Hibernate從數(shù)據(jù)庫中取出主鍵的最大值(每個(gè)session只取1次),,以該值為基礎(chǔ),,每次增量為1,在內(nèi)存中生成主鍵,,不依賴于底層的數(shù)據(jù)庫,,因此可以跨數(shù)據(jù)庫。
Hibernate調(diào)用org.hibernate.id.IncrementGenerator類里面的generate()方法,,使用select max(idColumnName) from tableName語句獲取主鍵最大值,。該方法被聲明成了synchronized,所以在一個(gè)獨(dú)立的Java虛擬機(jī)內(nèi)部是沒有問題的,,然而,,在多個(gè)JVM同時(shí)并發(fā)訪問數(shù)據(jù)庫select max時(shí)就可能取出相同的值,再insert就會(huì)發(fā)生Dumplicate entry的錯(cuò)誤,。所以只能有一個(gè)Hibernate應(yīng)用進(jìn)程訪問數(shù)據(jù)庫,,否則就可能產(chǎn)生主鍵沖突,,所以不適合多進(jìn)程并發(fā)更新數(shù)據(jù)庫,,適合單一進(jìn)程訪問數(shù)據(jù)庫,,不能用于群集環(huán)境,。
官方文檔:只有在沒有其他進(jìn)程往同一張表中插入數(shù)據(jù)時(shí)才能使用,在集群下不要使用,。
3、hilo
hilo(高低位方式high low)是hibernate中最常用的一種生成方式,,需要一張額外的表保存hi的值,。保存hi值的表至少有一條記錄(只與第一條記錄有關(guān)),否則會(huì)出現(xiàn)錯(cuò)誤,。可以跨數(shù)據(jù)庫,。
<param name="table">hibernate_hilo</param>
<param name="column">next_hi</param>
<param name="max_lo">100</param>
也可以省略table和column配置,其默認(rèn)的表為hibernate_unique_key,,列為next_hi
hilo生成器生成主鍵的過程(以hibernate_unique_key表,,next_hi列為例):
1. 獲得hi值:讀取并記錄數(shù)據(jù)庫的hibernate_unique_key表中next_hi字段的值,數(shù)據(jù)庫中此字段值加1保存,。
2. 獲得lo值:從0到max_lo循環(huán)取值,,差值為1,當(dāng)值為max_lo值時(shí),,重新獲取hi值,,然后lo值繼續(xù)從0到max_lo循環(huán)。
注意:當(dāng)hi值是0的時(shí)候,,那么第一個(gè)值不是0*(max_lo+1)+0=0,而是lo跳過0從1開始,,直接是1,、2、3……
那max_lo配置多大合適呢,?
這要根據(jù)具體情況而定,,如果系統(tǒng)一般不重啟,而且需要用此表建立大量的主鍵,,可以吧max_lo配置大一點(diǎn),,這樣可以減少讀取數(shù)據(jù)表的次數(shù),提高效率,;反之,,如果服務(wù)器經(jīng)常重啟,可以吧max_lo配置小一點(diǎn),,可以避免每次重啟主鍵之間的間隔太大,,造成主鍵值主鍵不連貫。
4、seqhilo
與hilo類似,,通過hi/lo算法實(shí)現(xiàn)的主鍵生成機(jī)制,,只是將hilo中的數(shù)據(jù)表換成了序列sequence,,需要數(shù)據(jù)庫中先創(chuàng)建sequence,適用于支持sequence的數(shù)據(jù)庫,,如oracle,。
5,、sequence
采用數(shù)據(jù)庫提供的sequence機(jī)制生成主鍵,需要數(shù)據(jù)庫支持sequence,。如oralce,、DB、SAP DB,、PostgerSQL,、McKoi中的sequence。MySQL這種不支持sequence的數(shù)據(jù)庫則不行(可以使用identity),。
<param name="sequence">hibernate_id</param>
Hibernate生成主鍵時(shí),,查找sequence并賦給主鍵值,主鍵值由數(shù)據(jù)庫生成,,Hibernate不負(fù)責(zé)維護(hù),,使用時(shí)必須先創(chuàng)建一個(gè)sequence,如果不指定sequence名稱,,則使用Hibernate默認(rèn)的sequence,,名稱為hibernate_sequence,前提要在數(shù)據(jù)庫中創(chuàng)建該sequence,。
6,、identity
identity由底層數(shù)據(jù)庫生成標(biāo)識(shí)符,。identity是由數(shù)據(jù)庫自己生成的,但這個(gè)主鍵必須設(shè)置為自增長,,使用identity的前提條件是底層數(shù)據(jù)庫支持自動(dòng)增長字段類型,,如DB2、SQL Server,、MySQL,、Sybase和HypersonicSQL等,Oracle這類沒有自增字段的則不支持,。
例:如果使用MySQL數(shù)據(jù)庫,,則主鍵字段必須設(shè)置成auto_increment。
id int(11) primary key auto_increment
7,、native
native由hibernate根據(jù)使用的數(shù)據(jù)庫自行判斷采用identity、hilo,、sequence其中一種作為主鍵生成方式,,靈活性很強(qiáng),。如果能支持identity則使用identity,,如果支持sequence則使用sequence。
例如MySQL使用identity,,Oracle使用sequence
注意:如果Hibernate自動(dòng)選擇sequence或者hilo,,則所有的表的主鍵都會(huì)從Hibernate默認(rèn)的sequence或hilo表中取。并且,,有的數(shù)據(jù)庫對(duì)于默認(rèn)情況主鍵生成測(cè)試的支持,,效率并不是很高。
使用sequence或hilo時(shí),,可以加入?yún)?shù),,指定sequence名稱或hi值表名稱等,如
<param name="sequence">hibernate_id</param>
8、uuid
UUID:Universally Unique Identifier,,是指在一臺(tái)機(jī)器上生成的數(shù)字,,它保證對(duì)在同一時(shí)空中的所有機(jī)器都是唯一的。按照開放軟件基金會(huì)(OSF)制定的標(biāo)準(zhǔn)計(jì)算,,用到了以太網(wǎng)卡地址,、納秒級(jí)時(shí)間、芯片ID碼和許多可能的數(shù)字,,標(biāo)準(zhǔn)的UUID格式為:
xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)
其中每個(gè) x 是 0-9 或 a-f 范圍內(nèi)的一個(gè)十六進(jìn)制的數(shù)字,。
Hibernate在保存對(duì)象時(shí),生成一個(gè)UUID字符串作為主鍵,,保證了唯一性,,但其并無任何業(yè)務(wù)邏輯意義,只能作為主鍵,,唯一缺點(diǎn)長度較大,,32位(Hibernate將UUID中間的“-”刪除了)的字符串,占用存儲(chǔ)空間大,,但是有兩個(gè)很重要的優(yōu)點(diǎn),,Hibernate在維護(hù)主鍵時(shí),,不用去數(shù)據(jù)庫查詢,從而提高效率,,而且它是跨數(shù)據(jù)庫的,,以后切換數(shù)據(jù)庫極其方便。
9,、guid
GUID:Globally Unique Identifier全球唯一標(biāo)識(shí)符,也稱作 UUID,,是一個(gè)128位長的數(shù)字,,用16進(jìn)制表示。算法的核心思想是結(jié)合機(jī)器的網(wǎng)卡,、當(dāng)?shù)貢r(shí)間,、一個(gè)隨即數(shù)來生成GUID。從理論上講,,如果一臺(tái)機(jī)器每秒產(chǎn)生10000000個(gè)GUID,,則可以保證(概率意義上)3240年不重復(fù)。
Hibernate在維護(hù)主鍵時(shí),,先查詢數(shù)據(jù)庫,,獲得一個(gè)uuid字符串,該字符串就是主鍵值,,該值唯一,,缺點(diǎn)長度較大,支持?jǐn)?shù)據(jù)庫有限,,優(yōu)點(diǎn)同uuid,,跨數(shù)據(jù)庫,但是仍然需要訪問數(shù)據(jù)庫,。
注意:長度因數(shù)據(jù)庫不同而不同
MySQL中使用select uuid()語句獲得的為36位(包含標(biāo)準(zhǔn)格式的“-”)
Oracle中,,使用select rawtohex(sys_guid()) from dual語句獲得的為32位(不包含“-”)
10,、foreign
使用另外一個(gè)相關(guān)聯(lián)的對(duì)象的主鍵作為該對(duì)象主鍵,。主要用于一對(duì)一關(guān)系中,。
11、select
12,、其他注釋方式配置
如MySQL,會(huì)使用自增字段,,需要將主鍵設(shè)置成auto_increment,。
每次需要主鍵值時(shí),,查詢名為"hibernate_table"的表,查找主鍵列"gen_pk"值為"2"記錄,,得到這條記錄的"gen_val"值,,根據(jù)這個(gè)值,和allocationSize的值生成主鍵值,。
13,、小結(jié)
|
自動(dòng)增長字段 |
序列 |
MySQL |
是 |
|
Oracle |
|
是 |
DB2 |
是 |
是 |
MS SQL Server |
是 |
|
Sybase |
是 |
|
HypersonicSQL |
是 |
|
PostgreSQL |
|
是 |
SAP DB |
|
是 |
HSQLDB |
是 |
|
Infomix |
是 |
|
當(dāng)用戶為Hibernate自行提供連接,,或者Hibernate通過JTA,,從應(yīng)用服務(wù)器的數(shù)據(jù)源獲取數(shù)據(jù)庫連接時(shí),無法使用hilo,,因?yàn)檫@不能保證hilo單獨(dú)在新的數(shù)據(jù)庫連接的事務(wù)中訪問hi值表,,這種情況,如果數(shù)據(jù)庫支持序列,,可以使用seqhilo,。