hibernate 序列_Hibernate身份,序列和表(序列)生成器
hibernate 序列
介紹
在上一篇文章中,我談到了不同的數據庫標識符策略。 這篇文章將比較最常見的替代主要關鍵策略:
- 身份
- 序列
- 表(序列)
身份
IDENTITY類型(包括在SQL:2003標準中)受以下支持:
- SQL服務器
- MySQL(AUTO_INCREMENT)
- DB2
- 數據庫
IDENTITY生成器允許按需自動增加integer / bigint列。 增量過程發生在當前正在運行的事務之外,因此回滾可能最終丟棄已分配的值(可能會發生值差距)。
增量過程非常有效,因為它使用了數據庫內部的輕量級鎖定機制,而不是重量級的事務性過程粒度鎖定。
唯一的缺點是我們無法在執行INSERT語句之前知道新分配的值。 這種限制阻礙了Hibernate采用的“事務后寫”刷新策略。 因此,Hibernates使用IDENTITY生成器為實體禁用JDBC批處理支持。
對于以下示例,我們將啟用會話工廠JDBC批處理:
properties.put("hibernate.order_inserts", "true"); properties.put("hibernate.order_updates", "true"); properties.put("hibernate.jdbc.batch_size", "2");讓我們使用IDENTITY生成策略定義一個實體:
@Entity(name = "identityIdentifier") public static class IdentityIdentifier {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id; }持續存在5個實體:
doInTransaction(new TransactionCallable<Void>() {@Overridepublic Void execute(Session session) {for (int i = 0; i < 5; i++) {session.persist(new IdentityIdentifier());}session.flush();return null;} });將在另一個查詢之后執行一個查詢(不涉及JDBC批處理):
Query:{[insert into identityIdentifier (id) values (default)][]} Query:{[insert into identityIdentifier (id) values (default)][]} Query:{[insert into identityIdentifier (id) values (default)][]} Query:{[insert into identityIdentifier (id) values (default)][]} Query:{[insert into identityIdentifier (id) values (default)][]}除了禁用JDBC批處理之外,IDENTITY生成器策略不適用于每個具體類繼承模型的Table ,因為可能存在多個具有相同標識符的子類實體,并且基類查詢最終將檢索具有相同標識符的實體(甚至(如果屬于不同類型)。
序列
SEQUENCE生成器(在SQL:2003標準中定義)受以下支持:
- Oracle
- SQL服務器
- PostgreSQL
- DB2
- 數據庫
SEQUENCE是一個數據庫對象,它在每個連續的請求上生成增量整數。 SEQUENCES比IDENTIFIER列靈活得多,因為:
- SEQUENCE是無表的,并且可以將同一序列分配給多個列或表
- SEQUENCE可以預分配值以提高性能
- SEQUENCE可以定義一個增量步驟,使我們可以受益于“池化” Hilo算法
- SEQUENCE不會限制Hibernate JDBC批處理
- SEQUENCE不會限制Hibernate繼承模型
讓我們使用SEQUENCE生成策略定義一個實體:
@Entity(name = "sequenceIdentifier") public static class SequenceIdentifier {@Id@GenericGenerator(name = "sequence", strategy = "sequence", parameters = {@org.hibernate.annotations.Parameter(name = "sequenceName", value = "sequence"),@org.hibernate.annotations.Parameter(name = "allocationSize", value = "1"),})@GeneratedValue(generator = "sequence", strategy=GenerationType.SEQUENCE)private Long id; }我使用了“序列”生成器,因為我不想讓Hibernate代表我們選擇SequenceHiLoGenerator或SequenceStyleGeneGenerator 。
添加5個實體:
doInTransaction(new TransactionCallable<Void>() {@Overridepublic Void execute(Session session) {for (int i = 0; i < 5; i++) {session.persist(new SequenceIdentifier());}session.flush();return null;} });生成以下查詢:
Query:{[call next value for hibernate_sequence][]} Query:{[call next value for hibernate_sequence][]} Query:{[call next value for hibernate_sequence][]} Query:{[call next value for hibernate_sequence][]} Query:{[call next value for hibernate_sequence][]} Query:{[insert into sequenceIdentifier (id) values (?)][1]} {[insert into sequenceIdentifier (id) values (?)][2]} Query:{[insert into sequenceIdentifier (id) values (?)][3]} {[insert into sequenceIdentifier (id) values (?)][4]} Query:{[insert into sequenceIdentifier (id) values (?)][5]}該表中的插入是批量處理的,但是我們知道在插入實體之前有5個序列調用。 這可以通過使用HILO算法進行優化。
表(序列)
生成序列還有另一種與數據庫無關的替代方法。 一個或多個表可用于保存標識符序列計數器。 但這意味著要犧牲寫入性能來實現數據庫的可移植性。
盡管IDENTITY和SEQUENCES沒有事務,但是使用數據庫表授權ACID來同步多個并發id生成請求。
通過使用行級鎖定,可以實現這一點,而行級鎖定的成本要高于IDENTITY或SEQUENCE生成器。
必須在單獨的數據庫事務中計算序列,這需要IsolationDelegate機制,該機制同時支持本地(JDBC)和全局(JTA)事務。
- 對于本地事務,它必須打開一個新的JDBC連接,因此對當前的連接池機制施加了更大的壓力。
- 對于全局事務,它需要掛起當前正在運行的事務。 在生成序列值之后,必須恢復實際事務。 此過程需要自己承擔費用,因此可能會影響整體應用程序性能。
讓我們使用TABLE生成策略定義一個Entity:
@Entity(name = "tableIdentifier") public static class TableSequenceIdentifier {@Id@GenericGenerator(name = "table", strategy = "enhanced-table", parameters = {@org.hibernate.annotations.Parameter(name = "table_name", value = "sequence_table")})@GeneratedValue(generator = "table", strategy=GenerationType.TABLE)private Long id; }我使用了較新的“增強表”生成器,因為舊式“表”生成器已被棄用。
添加5個實體:
doInTransaction(new TransactionCallable<Void>() {@Overridepublic Void execute(Session session) {for (int i = 0; i < 5; i++) {session.persist(new TableSequenceIdentifier());}session.flush();return null;} });生成以下查詢:
Query:{[select tbl.next_val from sequence_table tbl where tbl.sequence_name=? for update][default]} Query:{[insert into sequence_table (sequence_name, next_val) values (?,?)][default,1]} Query:{[update sequence_table set next_val=? where next_val=? and sequence_name=?][2,1,default]} Query:{[select tbl.next_val from sequence_table tbl where tbl.sequence_name=? for update][default]} Query:{[update sequence_table set next_val=? where next_val=? and sequence_name=?][3,2,default]} Query:{[select tbl.next_val from sequence_table tbl where tbl.sequence_name=? for update][default]} Query:{[update sequence_table set next_val=? where next_val=? and sequence_name=?][4,3,default]} Query:{[select tbl.next_val from sequence_table tbl where tbl.sequence_name=? for update][default]} Query:{[update sequence_table set next_val=? where next_val=? and sequence_name=?][5,4,default]} Query:{[select tbl.next_val from sequence_table tbl where tbl.sequence_name=? for update][default]} Query:{[update sequence_table set next_val=? where next_val=? and sequence_name=?][6,5,default]} Query:{[insert into tableIdentifier (id) values (?)][1]} {[insert into tableIdentifier (id) values (?)][2]} Query:{[insert into tableIdentifier (id) values (?)][3]} {[insert into tableIdentifier (id) values (?)][4]} Query:{[insert into tableIdentifier (id) values (?)][5]}表生成器允許JDBC批處理,但它訴諸于SELECT FOR UPDATE查詢。 行級別鎖定絕對比使用本機IDENTITY或SEQUENCE效率低。
因此,根據您的應用程序需求,您可以選擇多個選項。 沒有一個單一的獲勝策略,每一個都有優點和缺點。
- 代碼可在GitHub上獲得 。
翻譯自: https://www.javacodegeeks.com/2014/07/hibernate-identity-sequence-and-table-sequence-generator.html
hibernate 序列
總結
以上是生活随笔為你收集整理的hibernate 序列_Hibernate身份,序列和表(序列)生成器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑企业微信下载(电脑企业微信下载的文件
- 下一篇: 对编写的代码进行单元测试_编写数据访问代