Hibernate和UUID标识符
介紹
在我以前的文章中,我討論了UUID代理密鑰以及用例 , 這些用例比更常見(jiàn)的自動(dòng)遞增標(biāo)識(shí)符更合適。
UUID數(shù)據(jù)庫(kù)類型
有幾種表示128位UUID的方法,每當(dāng)有疑問(wèn)時(shí),我都希望向Stack Exchange尋求專家建議。
由于通常對(duì)表標(biāo)識(shí)符進(jìn)行索引,因此數(shù)據(jù)庫(kù)類型越緊湊,索引所需的空間就越少。 從效率最高到最低,這是我們的選擇:
Hibernate提供了許多標(biāo)識(shí)符策略供您選擇,對(duì)于UUID標(biāo)識(shí)符,我們有三種選擇:
- 分配的生成器以及應(yīng)用程序邏輯UUID生成
- 十六進(jìn)制“ uuid”字符串生成器
- 更靈活的“ uuid2”生成器,允許我們使用java.lang.UUID ,16字節(jié)數(shù)組或十六進(jìn)制String值
分配的發(fā)電機(jī)
分配的生成器允許應(yīng)用程序邏輯控制實(shí)體標(biāo)識(shí)符生成過(guò)程。 通過(guò)簡(jiǎn)單地省略標(biāo)識(shí)符生成器定義,Hibernate將考慮分配的標(biāo)識(shí)符。 此示例使用BINARY(16)列類型,因?yàn)槟繕?biāo)數(shù)據(jù)庫(kù)是HSQLDB 。
@Entity(name = "assignedIdentifier") public static class AssignedIdentifier {@Id@Column(columnDefinition = "BINARY(16)")private UUID uuid;public AssignedIdentifier() {}public AssignedIdentifier(UUID uuid) {this.uuid = uuid;} }持久實(shí)體:
session.persist(new AssignedIdentifier(UUID.randomUUID())); session.flush();恰好生成一個(gè)INSERT語(yǔ)句:
Query:{[insert into assignedIdentifier (uuid) values (?)][[B@76b0f8c3]}讓我們看看發(fā)出合并時(shí)會(huì)發(fā)生什么:
session.merge(new AssignedIdentifier(UUID.randomUUID())); session.flush();這次我們同時(shí)獲得了SELECT和INSERT:
Query:{[select assignedid0_.uuid as uuid1_0_0_ from assignedIdentifier assignedid0_ where assignedid0_.uuid=?][[B@23e9436c]} Query:{[insert into assignedIdentifier (uuid) values (?)][[B@2b37d486]}persist方法采用一個(gè)臨時(shí)實(shí)體,并將其附加到當(dāng)前的Hibernate會(huì)話。 如果已經(jīng)存在一個(gè)連接的實(shí)體,或者如果當(dāng)前的實(shí)體是分離的,我們將得到一個(gè)異常。
合并操作會(huì)將當(dāng)前對(duì)象狀態(tài)復(fù)制到現(xiàn)有的持久實(shí)體(如果有)中。 此操作適用于臨時(shí)實(shí)體和分離實(shí)體,但是對(duì)于臨時(shí)實(shí)體持久化比合并操作有效得多。
對(duì)于分配的標(biāo)識(shí)符,合并將始終需要進(jìn)行選擇,因?yàn)镠ibernate無(wú)法知道是否已經(jīng)存在具有相同標(biāo)識(shí)符的持久實(shí)體。 對(duì)于其他標(biāo)識(shí)符生成器,??Hibernate會(huì)尋找一個(gè)空標(biāo)識(shí)符,以判斷該實(shí)體是否處于過(guò)渡狀態(tài)。
這就是為什么Spring Data SimpleJpaRepository#save(S實(shí)體)方法不是使用分配的標(biāo)識(shí)符的實(shí)體的最佳選擇的原因:
@Transactional public <S extends T> S save(S entity) {if (entityInformation.isNew(entity)) {em.persist(entity);return entity;} else {return em.merge(entity);} }對(duì)于分配的標(biāo)識(shí)符,此方法將始終選擇合并而不是持久化,因此對(duì)于每個(gè)新插入的實(shí)體,您將同時(shí)獲得SELECT和INSERT。
UUID生成器
這次我們不會(huì)自己分配標(biāo)識(shí)符,而是讓Hibernate代表我們生成它。 當(dāng)遇到一個(gè)空標(biāo)識(shí)符時(shí),Hibernate假定一個(gè)臨時(shí)實(shí)體,為其生成一個(gè)新的標(biāo)識(shí)符值。 這次,合并操作將不需要在插入過(guò)渡實(shí)體之前進(jìn)行選擇查詢。
UUIDHexGenerator
UUID十六進(jìn)制生成器是最早的UUID標(biāo)識(shí)符生成器,??它以“ uuid”類型注冊(cè)。 它可以生成具有以下模式的32位十六進(jìn)制UUID字符串值(也可以使用分隔符):8 {sep} 8 {sep} 4 {sep} 8 {sep} 4。
此生成器不符合IETF RFC 4122 ,它使用8-4-4-4-12數(shù)字表示。
@Entity(name = "uuidIdentifier") public static class UUIDIdentifier {@GeneratedValue(generator = "uuid")@GenericGenerator(name = "uuid", strategy = "uuid")@Column(columnDefinition = "CHAR(32)")@Idprivate String uuidHex; }持久化或合并臨時(shí)實(shí)體:
session.persist(new UUIDIdentifier()); session.flush(); session.merge(new UUIDIdentifier()); session.flush();每個(gè)操作生成一個(gè)INSERT語(yǔ)句:
Query:{[insert into uuidIdentifier (uuidHex) values (?)][2c929c6646f02fda0146f02fdbfa0000]} Query:{[insert into uuidIdentifier (uuidHex) values (?)][2c929c6646f02fda0146f02fdbfc0001]}您可以檢出發(fā)送到SQL INSERT查詢的字符串參數(shù)值。
UUIDGenerator
較新的UUID生成器符合IETF RFC 4122(變體2),并提供可插拔生成策略。 它以“ uuid2”類型注冊(cè),并且提供了更大的類型范圍供您選擇:
- java.lang.UUID
- 16字節(jié)數(shù)組
- 十六進(jìn)制字符串值
持久化或合并臨時(shí)實(shí)體:
session.persist(new UUID2Identifier()); session.flush(); session.merge(new UUID2Identifier()); session.flush();每個(gè)操作生成一個(gè)INSERT語(yǔ)句:
Query:{[insert into uuid2Identifier (uuid) values (?)][[B@68240bb]} Query:{[insert into uuid2Identifier (uuid) values (?)][[B@577c3bfa]}當(dāng)我們配置@Id列定義時(shí),此SQL INSERT查詢正在使用字節(jié)數(shù)組。
- 代碼可在GitHub上獲得 。
翻譯自: https://www.javacodegeeks.com/2014/07/hibernate-and-uuid-identifiers.html
總結(jié)
以上是生活随笔為你收集整理的Hibernate和UUID标识符的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 调低备案价好处(调低备案价)
- 下一篇: 安卓1024以下端口(安卓1024)