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