[英]nextVal from PostgreSQL sequence in Hibernate fetch sequence multiple times
對於業務邏輯,我們需要使用直接在數據庫中而不是在 Hibernate 中定義的序列中的下一個值來更新記錄(因為並不總是應用於插入/更新)
為此,我們在 PostgreSQL 中定義了一個序列,其中 DDL 為:
CREATE SEQUENCE public.facturaproveedor_numeracionperiodofiscal_seq
INCREMENT 1 MINVALUE 1
MAXVALUE 9223372036854775807 START 1
CACHE 1;
然后在 DAO 中,當某些條件為真時,我們通過以下方式獲得 nextVal:
Query query = sesion.createSQLQuery("SELECT nextval('facturaproveedor_numeracionperiodofiscal_seq')");
Long siguiente = ((BigInteger) query.uniqueResult()).longValue();
但是分配的值不是連續的。 查看 Hibernate output 日志,我們看到在同一事務中對序列進行了四個提取:
Hibernate: SELECT nextval('facturaproveedor_numeracionperiodofiscal_seq') as num
Hibernate: SELECT nextval('facturaproveedor_numeracionperiodofiscal_seq') as num
Hibernate: SELECT nextval('facturaproveedor_numeracionperiodofiscal_seq') as num
Hibernate: SELECT nextval('facturaproveedor_numeracionperiodofiscal_seq') as num
為什么會這樣? 這是為了捕捉目的嗎? 有辦法禁用這個嗎? 或者這種解決方法不正確?
Hibernate通常不會生成看起來像這樣的獨立nextval
調用,因此如果您的應用程序執行多次提取操作,我也不會感到驚訝。 您需要收集更多的跟蹤信息以確保。
我認為您可能會遇到更大的問題。 如果您關心序列跳過值或留下漏洞,那么您正在使用錯誤的工具來完成工作,則應該在UPDATE
的表中使用計數器,可能是UPDATE my_id_generator SET id = id + 1 RETURNING id
。 這將鎖定並發事務 ,並確保如果事務回滾,則撤消更新 。
相反,序列並行運行,這意味着在事務回滾時,不可能回滾序列增量(請參見PostgreSQL文檔)。 因此,它們通常不適合用於會計目的,例如發票編號和您需要無間斷序列的其他事物。
對於沒有特定要求僅有時生成一個值的其他讀者:不要手動生成序列值; 使用@GeneratedValue
批注。
在Hibernate 3.6及更高版本中,應在Hibernate屬性中設置hibernate.id.new_generator_mappings
。
假設您要從PostgreSQL SERIAL
列映射生成的密鑰,請使用以下映射:
@Id
@SequenceGenerator(name="mytable_id_seq",sequenceName="mytable_id_seq", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="mytable_id_seq")
如果您忽略了allocationSize
那么Hibernate會認為它是默認值50
並且無法檢查序列是否實際遞增50,因此它嘗試插入已使用的ID並失敗。
Hibernate / JPA無法自動為您的非id屬性創建一個值。 @GeneratedValue批注僅與@Id結合使用以創建自動編號
Hibernate 緩存查詢結果。
注意“as num”,看起來 hibernate 也在改變 SQL。
您應該能夠告訴 Hibernate 不要緩存結果
query.setCacheable(false);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.