日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hibernate各种主键生成策略与配置详解

發(fā)布時間:2023/12/31 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hibernate各种主键生成策略与配置详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??

1、assigned

主鍵由外部程序負(fù)責(zé)生成,在 save() 之前必須指定一個。Hibernate不負(fù)責(zé)維護(hù)主鍵生成。與Hibernate和底層數(shù)據(jù)庫都無關(guān),可以跨數(shù)據(jù)庫。在存儲對象前,必須要使用主鍵的setter方法給主鍵賦值,至于這個值怎么生成,完全由自己決定,這種方法應(yīng)該盡量避免。

<id name="id" column="id">

<generator class="assigned" />

</id>

“ud”是自定義的策略名,人為起的名字,后面均用“ud”表示。


特點:可以跨數(shù)據(jù)庫,人為控制主鍵生成,應(yīng)盡量避免。


2、increment


由Hibernate從數(shù)據(jù)庫中取出主鍵的最大值(每個session只取1次),以該值為基礎(chǔ),每次增量為1,在內(nèi)存中生成主鍵,不依賴于底層的數(shù)據(jù)庫,因此可以跨數(shù)據(jù)庫。


<id name="id" column="id">


<generator class="increment" />


</id>


Hibernate調(diào)用org.hibernate.id.IncrementGenerator類里面的generate()方法,使用select max(idColumnName) from tableName語句獲取主鍵最大值。該方法被聲明成了synchronized,所以在一個獨立的Java虛擬機內(nèi)部是沒有問題的,然而,在多個JVM同時并發(fā)訪問數(shù)據(jù)庫select max時就可能取出相同的值,再insert就會發(fā)生Dumplicate entry的錯誤。所以只能有一個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ù)據(jù)庫,不適合多進(jìn)程并發(fā)更新數(shù)據(jù)庫,適合單一進(jìn)程訪問數(shù)據(jù)庫,不能用于群集環(huán)境。


3、hilo


hilo(高低位方式high low)是hibernate中最常用的一種生成方式,需要一張額外的表保存hi的值。保存hi值的表至少有一條記錄(只與第一條記錄有關(guān)),否則會出現(xiàn)錯誤。可以跨數(shù)據(jù)庫。


<id name="id" column="id">


<generator class="hilo">


<param name="table">hibernate_hilo</param>


<param name="column">next_hi</param>


<param name="max_lo">100</param>


</generator>


</id>


<param name="table">hibernate_hilo</param> 指定保存hi值的表名


<param name="column">next_hi</param> 指定保存hi值的列名


<param name="max_lo">100</param> 指定低位的最大值


也可以省略table和column配置,其默認(rèn)的表為hibernate_unique_key,列為next_hi


<id name="id" column="id">


<generator class="hilo">


<param name="max_lo">100</param>


</generator>


</id>


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值時,重新獲取hi值,然后lo值繼續(xù)從0到max_lo循環(huán)。


3. 根據(jù)公式 hi * (max_lo + 1) + lo計算生成主鍵值。


注意:當(dāng)hi值是0的時候,那么第一個值不是0*(max_lo+1)+0=0,而是lo跳過0從1開始,直接是1、2、3……


那max_lo配置多大合適呢?


這要根據(jù)具體情況而定,如果系統(tǒng)一般不重啟,而且需要用此表建立大量的主鍵,可以吧max_lo配置大一點,這樣可以減少讀取數(shù)據(jù)表的次數(shù),提高效率;反之,如果服務(wù)器經(jīng)常重啟,可以吧max_lo配置小一點,可以避免每次重啟主鍵之間的間隔太大,造成主鍵值主鍵不連貫。


特點:跨數(shù)據(jù)庫,hilo算法生成的標(biāo)志只能在一個數(shù)據(jù)庫中保證唯一。


4、seqhilo


與hilo類似,通過hi/lo算法實現(xiàn)的主鍵生成機制,只是將hilo中的數(shù)據(jù)表換成了序列sequence,需要數(shù)據(jù)庫中先創(chuàng)建sequence,適用于支持sequence的數(shù)據(jù)庫,如Oracle。


<id name="id" column="id">


<generator class="seqhilo">


<param name="sequence">hibernate_seq</param>


<param name="max_lo">100</param>


</generator>


</id>


?


特點:與hilo類似,只能在支持序列的數(shù)據(jù)庫中使用。

5、sequence


采用數(shù)據(jù)庫提供的sequence機制生成主鍵,需要數(shù)據(jù)庫支持sequence。如oralce、DB、SAP DB、PostgerSQL、McKoi中的sequence。MySQL這種不支持sequence的數(shù)據(jù)庫則不行(可以使用identity)。


<generator class="sequence">


<param name="sequence">hibernate_id</param>


</generator>


<param name="sequence">hibernate_id</param> 指定sequence的名稱


Hibernate生成主鍵時,查找sequence并賦給主鍵值,主鍵值由數(shù)據(jù)庫生成,Hibernate不負(fù)責(zé)維護(hù),使用時必須先創(chuàng)建一個sequence,如果不指定sequence名稱,則使用Hibernate默認(rèn)的sequence,名稱為hibernate_sequence,前提要在數(shù)據(jù)庫中創(chuàng)建該sequence。


特點:只能在支持序列的數(shù)據(jù)庫中使用,如Oracle。


6、identity


identity由底層數(shù)據(jù)庫生成標(biāo)識符。identity是由數(shù)據(jù)庫自己生成的,但這個主鍵必須設(shè)置為自增長,使用identity的前提條件是底層數(shù)據(jù)庫支持自動增長字段類型,如DB2、SQL Server、MySQL、Sybase和HypersonicSQL等,Oracle這類沒有自增字段的則不支持。


<id name="id" column="id">


<generator class="identity" />


</id>


例:如果使用MySQL數(shù)據(jù)庫,則主鍵字段必須設(shè)置成auto_increment。


id int(11) primary key auto_increment


特點:只能用在支持自動增長的字段數(shù)據(jù)庫中使用,如MySQL。


7、native


native由hibernate根據(jù)使用的數(shù)據(jù)庫自行判斷采用identity、hilo、sequence其中一種作為主鍵生成方式,靈活性很強。如果能支持identity則使用identity,如果支持sequence則使用sequence。


<id name="id" column="id">


<generator class="native" />


</id>


例如MySQL使用identity,Oracle使用sequence


注意:如果Hibernate自動選擇sequence或者h(yuǎn)ilo,則所有的表的主鍵都會從Hibernate默認(rèn)的sequence或hilo表中取。并且,有的數(shù)據(jù)庫對于默認(rèn)情況主鍵生成測試的支持,效率并不是很高。


使用sequence或hilo時,可以加入?yún)?shù),指定sequence名稱或hi值表名稱等,如


<param name="sequence">hibernate_id</param>


特點:根據(jù)數(shù)據(jù)庫自動選擇,項目中如果用到多個數(shù)據(jù)庫時,可以使用這種方式,使用時需要設(shè)置表的自增字段或建立序列,建立表等。


8、uuid


UUID:Universally Unique Identifier,是指在一臺機器上生成的數(shù)字,它保證對在同一時空中的所有機器都是唯一的。按照開放軟件基金會(OSF)制定的標(biāo)準(zhǔn)計算,用到了以太網(wǎng)卡地址、納秒級時間、芯片ID碼和許多可能的數(shù)字,標(biāo)準(zhǔn)的UUID格式為:


xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)


其中每個 x 是 0-9 或 a-f 范圍內(nèi)的一個十六進(jìn)制的數(shù)字。


<id name="id" column="id">


<generator class="uuid" />


</id>


Hibernate在保存對象時,生成一個UUID字符串作為主鍵,保證了唯一性,但其并無任何業(yè)務(wù)邏輯意義,只能作為主鍵,唯一缺點長度較大,32位(Hibernate將UUID中間的“-”刪除了)的字符串,占用存儲空間大,但是有兩個很重要的優(yōu)點,Hibernate在維護(hù)主鍵時,不用去數(shù)據(jù)庫查詢,從而提高效率,而且它是跨數(shù)據(jù)庫的,以后切換數(shù)據(jù)庫極其方便。


特點:uuid長度大,占用空間大,跨數(shù)據(jù)庫,不用訪問數(shù)據(jù)庫就生成主鍵值,所以效率高且能保證唯一性,移植非常方便,推薦使用。


9、guid


GUID:Globally Unique Identifier全球唯一標(biāo)識符,也稱作 UUID,是一個128位長的數(shù)字,用16進(jìn)制表示。算法的核心思想是結(jié)合機器的網(wǎng)卡、當(dāng)?shù)貢r間、一個隨即數(shù)來生成GUID。從理論上講,如果一臺機器每秒產(chǎn)生10000000個GUID,則可以保證(概率意義上)3240年不重復(fù)。


<id name="id" column="id">


<generator class="guid" />


</id>


Hibernate在維護(hù)主鍵時,先查詢數(shù)據(jù)庫,獲得一個uuid字符串,該字符串就是主鍵值,該值唯一,缺點長度較大,支持?jǐn)?shù)據(jù)庫有限,優(yōu)點同uuid,跨數(shù)據(jù)庫,但是仍然需要訪問數(shù)據(jù)庫。


注意:長度因數(shù)據(jù)庫不同而不同


MySQL中使用select uuid()語句獲得的為36位(包含標(biāo)準(zhǔn)格式的“-”)


Oracle中,使用select rawtohex(sys_guid()) from dual語句獲得的為32位(不包含“-”)?


特點:需要數(shù)據(jù)庫支持查詢uuid,生成時需要查詢數(shù)據(jù)庫,效率沒有uuid高,推薦使用uuid。


10、foreign


使用另外一個相關(guān)聯(lián)的對象的主鍵作為該對象主鍵。主要用于一對一關(guān)系中。


<id name="id" column="id">


<generator class="foreign">


<param name="property">user</param>


</generator>


</id>


<one-to-one name="user" class="domain.User" constrained="true" />


該例使用domain.User的主鍵作為本類映射的主鍵。


特點:很少使用,大多用在一對一關(guān)系中。


11、select


使用觸發(fā)器生成主鍵,主要用于早期的數(shù)據(jù)庫主鍵生成機制,能用到的地方非常少。


12、其他注釋方式配置


注釋方式與配置文件底層實現(xiàn)方式相同,只是配置的方式換成了注釋方式


自動增長,適用于支持自增字段的數(shù)據(jù)庫


@Id


@GeneratedValue(strategy = GenerationType.IDENTITY)


根據(jù)底層數(shù)據(jù)庫自動選擇方式,需要底層數(shù)據(jù)庫的設(shè)置


如MySQL,會使用自增字段,需要將主鍵設(shè)置成auto_increment。


@Id


@GeneratedValue(strategy = GenerationType.AUTO)


使用表存儲生成的主鍵,可以跨數(shù)據(jù)庫。


每次需要主鍵值時,查詢名為"hibernate_table"的表,查找主鍵列"gen_pk"值為"2"記錄,得到這條記錄的"gen_val"值,根據(jù)這個值,和allocationSize的值生成主鍵值。


@Id


@GeneratedValue(strategy = GenerationType.TABLE, generator = "ud")


@TableGenerator(name = "ud",


table = "hibernate_table",


pkColumnName = "gen_pk",


pkColumnValue = "2",


valueColumnName = "gen_val",


initialValue = 2,


allocationSize = 5)


使用序列存儲主鍵值


@Id


@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ud")


@SequenceGenerator(name = "ud",


sequenceName = "hibernate_seq",


allocationSize = 1,


initialValue = 2)


13、小結(jié)


1、為了保證對象標(biāo)識符的唯一性與不可變性,應(yīng)該讓Hibernate來為主鍵賦值,而不是程序。


2、正常使用Hibernate維護(hù)主鍵,最好將主鍵的setter方法設(shè)置成private,從而避免人為或程序修改主鍵,而使用assigned方式,就不能用private,否則無法給主鍵賦值。


2、Hibernate中唯一一種最簡單通用的主鍵生成器就是uuid。雖然是個32位難讀的長字符串,但是它沒有跨數(shù)據(jù)庫的問題,將來切換數(shù)據(jù)庫極其簡單方便,推薦使用!


3、自動增長字段類型與序列


數(shù)據(jù)庫


自動增長字段


序列


MySQL



?

Oracle


?


DB2




MS SQL Server



?

Sybase



?

HypersonicSQL



?

PostgreSQL


?


SAP DB


?


HSQLDB



?

Infomix



?

4、關(guān)于hilo機制注意:


hilo算法生成的標(biāo)志只能在一個數(shù)據(jù)庫中保證唯一。


當(dāng)用戶為Hibernate自行提供連接,或者Hibernate通過JTA,從應(yīng)用服務(wù)器的數(shù)據(jù)源獲取數(shù)據(jù)庫連接時,無法使用hilo,因為這不能保證hilo單獨在新的數(shù)據(jù)庫連接的事務(wù)中訪問hi值表,這種情況,如果數(shù)據(jù)庫支持序列,可以使用seqhilo。


5、使用identity、native、GenerationType.AUTO等方式生成主鍵時,只要用到自增字段,數(shù)據(jù)庫表的字段必須設(shè)置成自動增加的,否則出錯。


6、還有一些方法未列出來,例如uuid.hex,sequence-identity等,這些方法不是很常用,且已被其他方法代替,如uuid.hex,官方文檔里建議不使用,而直接使用uuid方法。


7、Hibernate的各版本主鍵生成策略配置有略微差別,但實現(xiàn)基本相同。如,有的版本默認(rèn)sequence不指定序列名,則使用名為hibernate_sequence的序列,有的版本則必須指定序列名。


8、還可以自定義主鍵生成策略,這里暫時不討論,只討論官方自帶生成策略。


轉(zhuǎn)載于:https://my.oschina.net/dyl226/blog/652622

總結(jié)

以上是生活随笔為你收集整理的Hibernate各种主键生成策略与配置详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。