pooled-jms_Hibernate隐藏的宝石:pooled-lo优化器
pooled-jms
介紹
在這篇文章中,我們將揭示一個序列標識符生成器,??它結合了標識符分配效率和與其他外部系統的互操作性(同時訪問底層數據庫系統)。
傳統上,有兩種序列標識符策略可供選擇。
- 序列標識符,對于每個新值分配總是命中數據庫。 即使使用數據庫序列預分配,我們也要花費大量的數據庫往返費用。
- seqhilo標識符,使用hi / lo算法。 該生成器在內存中計算一些標識符值,因此減少了數據庫往返調用。 這種優化技術的問題在于當前的數據庫序列值不再反映當前的最高內存生成值。 數據庫序列用作存儲區編號,因此其他系統很難與所討論的數據庫表進行互操作。 其他應用程序必須知道高/低標識符策略的內部工作方式,才能正確生成非沖突標識符。
增強的標識符
Hibernate提供了一類新的標識符生成器 ,解決了原始標識符生成器的許多缺點。 增強的標識符生成器沒有固定的標識符分配策略。 優化策略是可配置的,我們甚至可以提供自己的優化實現。 默認情況下,Hibernate隨附以下內置優化器 :
- none :每個標識符都是從數據庫中獲取的,因此等效于原始序列生成器。
- hi / lo :它使用hi / lo算法,與原始seqhilo生成器等效。
- 合并的 :此優化器使用高/低優化策略,但是當前內存中標識符的最高邊界是從實際數據庫序列值中提取的。
- pooled-lo :它類似于池優化器,但是數據庫序列值用作當前內存中的最低邊界
在正式發布公告中 , 公告了合并的優化器可與其他外部系統進行互操作:
即使其他應用程序也在插入值,我們也將是絕對安全的,因為SEQUENCE本身將處理應用此增量大小。
這實際上是我們正在尋找的東西。 當其他外部系統在同一數據庫表中同時插入行時,標識符生成器既高效又不會沖突。
測試時間
以下測試將檢查新的優化器如何與其他外部數據庫表插入配合使用。 在我們的例子中,外部系統將是在同一數據庫表/序列上的一些本機JDBC插入語句。
doInTransaction(new TransactionCallable<Void>() {@Overridepublic Void execute(Session session) {for (int i = 0; i < 8; i++) {session.persist(newEntityInstance());}session.flush();assertEquals(8, ((Number) session.createSQLQuery("SELECT COUNT(*) FROM sequenceIdentifier").uniqueResult()).intValue());insertNewRow(session);insertNewRow(session);insertNewRow(session);assertEquals(11, ((Number) session.createSQLQuery("SELECT COUNT(*) FROM sequenceIdentifier").uniqueResult()).intValue());List<Number> ids = session.createSQLQuery("SELECT id FROM sequenceIdentifier").list();for (Number id : ids) {LOGGER.debug("Found id: {}", id);}for (int i = 0; i < 3; i++) {session.persist(newEntityInstance());}session.flush();return null;} });池優化器
我們將首先使用池優化器策略:
@Entity(name = "sequenceIdentifier") public static class PooledSequenceIdentifier {@Id@GenericGenerator(name = "sequenceGenerator", strategy = "enhanced-sequence",parameters = {@org.hibernate.annotations.Parameter(name = "optimizer", value = "pooled"),@org.hibernate.annotations.Parameter(name = "initial_value", value = "1"),@org.hibernate.annotations.Parameter(name = "increment_size", value = "5")})@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")private Long id; }運行測試最終會引發以下異常:
DEBUG [main]: n.t.d.l.SLF4JQueryLoggingListener - Name: Time:0 Num:1 Query:{[insert into sequenceIdentifier (id) values (?)][9]} DEBUG [main]: n.t.d.l.SLF4JQueryLoggingListener - Name: Time:0 Num:1 Query:{[insert into sequenceIdentifier (id) values (?)][10]} DEBUG [main]: n.t.d.l.SLF4JQueryLoggingListener - Name: Time:0 Num:1 Query:{[insert into sequenceIdentifier (id) values (?)][26]} WARN [main]: o.h.e.j.s.SqlExceptionHelper - SQL Error: -104, SQLState: 23505 ERROR [main]: o.h.e.j.s.SqlExceptionHelper - integrity constraint violation: unique constraint or index violation; SYS_PK_10104 table: SEQUENCEIDENTIFIER ERROR [main]: c.v.h.m.l.i.PooledSequenceIdentifierTest - Pooled optimizer threw org.hibernate.exception.ConstraintViolationException: could not execute statementat org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:72) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final] Caused by: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: unique constraint or index violation; SYS_PK_10104 table: SEQUENCEIDENTIFIERat org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) ~[hsqldb-2.3.2.jar:2.3.2]我不確定這是錯誤還是僅是設計限制,但是合并的優化器不滿足互操作性要求。
為了可視化發生的情況,我在下圖中總結了序列調用:
當池優化器檢索當前序列值時,它將使用它來計算最低的內存邊界。 最小值是實際的先前序列值,并且其他外部INSERT語句可能已經使用了該值。
Pool-lo優化器
幸運的是,還有另外一個要測試的優化器(參考文檔中未提及)。 pool-lo優化器使用當前數據庫序列值作為最低的內存邊界,因此其他系統可以自由使用下一個序列值而不會冒標識符沖突的風險:
@Entity(name = "sequenceIdentifier") public static class PooledLoSequenceIdentifier {@Id@GenericGenerator(name = "sequenceGenerator", strategy = "enhanced-sequence",parameters = {@org.hibernate.annotations.Parameter(name = "optimizer",value = "pooled-lo"),@org.hibernate.annotations.Parameter(name = "initial_value", value = "1"),@org.hibernate.annotations.Parameter(name = "increment_size", value = "5")})@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")private Long id; }為了更好地了解此優化器的內部工作原理,下圖總結了標識符分配過程:
結論
隱藏的寶石是大多數人甚至都不知道其存在的巨大功能之一。 pool-lo優化器非常有用,但是大多數人甚至都不知道它的存在。
- 代碼可在GitHub上獲得 。
翻譯自: https://www.javacodegeeks.com/2014/07/hibernate-hidden-gem-the-pooled-lo-optimizer.html
pooled-jms
總結
以上是生活随笔為你收集整理的pooled-jms_Hibernate隐藏的宝石:pooled-lo优化器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ddos攻击器安卓版下载官网(ddos攻
- 下一篇: 研发费用加计扣除需要备案吗(研发费用加计