[英]nextVal from PostgreSQL sequence in Hibernate fetch sequence multiple times
For business logic we need to update a record with the next value from a sequence defined directly in database and not in Hibernate (because is not always applied on insert / updates)对于业务逻辑,我们需要使用直接在数据库中而不是在 Hibernate 中定义的序列中的下一个值来更新记录(因为并不总是应用于插入/更新)
For this purpose we have a sequence defined in PostgreSQL witch DDL is:为此,我们在 PostgreSQL 中定义了一个序列,其中 DDL 为:
CREATE SEQUENCE public.facturaproveedor_numeracionperiodofiscal_seq
INCREMENT 1 MINVALUE 1
MAXVALUE 9223372036854775807 START 1
CACHE 1;
Then in DAO, when some conditions are true, we get the nextVal via:然后在 DAO 中,当某些条件为真时,我们通过以下方式获得 nextVal:
Query query = sesion.createSQLQuery("SELECT nextval('facturaproveedor_numeracionperiodofiscal_seq')");
Long siguiente = ((BigInteger) query.uniqueResult()).longValue();
But the values asigned aren't consecutive.但是分配的值不是连续的。 Looking the Hibernate output log we see four fetchs to the sequence in the same transaction:
查看 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
Why is this happening?为什么会这样? Is this for catching purposes?
这是为了捕捉目的吗? There is a way to disable this?
有办法禁用这个吗? Or this workaround is not correct?
或者这种解决方法不正确?
Hibernate won't usually generate standalone nextval
calls that look like that, so I won't be too surprised if it's your application doing the multiple fetches. Hibernate通常不会生成看起来像这样的独立
nextval
调用,因此如果您的应用程序执行多次提取操作,我也不会感到惊讶。 You'll need to collect more tracing information to be sure. 您需要收集更多的跟踪信息以确保。
I think you may have a bigger problem though. 我认为您可能会遇到更大的问题。 If you care about sequences skipping values or leaving holes then you're using the wrong tool for the job, you should be using a counter in a table that you
UPDATE
, probably UPDATE my_id_generator SET id = id + 1 RETURNING id
. 如果您关心序列跳过值或留下漏洞,那么您正在使用错误的工具来完成工作,则应该在
UPDATE
的表中使用计数器,可能是UPDATE my_id_generator SET id = id + 1 RETURNING id
。 This locks out concurrent transactions and also ensures that if the transaction rolls back, the update is undone . 这将锁定并发事务 ,并确保如果事务回滚,则撤消更新 。
Sequences by contrast operate in parallel, which means that it's impossible to roll back a sequence increment when a transaction rolls back (see the PostgreSQL documentation). 相反,序列并行运行,这意味着在事务回滚时,不可能回滚序列增量(请参见PostgreSQL文档)。 So they're generally not suitable for accounting purposes like invoice numbering and other things where you require a gapless sequence.
因此,它们通常不适合用于会计目的,例如发票编号和您需要无间断序列的其他事物。
For other readers who don't have the specific requirement to only sometimes generate a value: don't generate the sequence values manually; 对于没有特定要求仅有时生成一个值的其他读者:不要手动生成序列值; use a
@GeneratedValue
annotation. 使用
@GeneratedValue
批注。
In Hibernate 3.6 and newer, you should set hibernate.id.new_generator_mappings
in your Hibernate properties. 在Hibernate 3.6及更高版本中,应在Hibernate属性中设置
hibernate.id.new_generator_mappings
。
Assuming you're mapping a generated key from a PostgreSQL SERIAL
column, use the mapping: 假设您要从PostgreSQL
SERIAL
列映射生成的密钥,请使用以下映射:
@Id
@SequenceGenerator(name="mytable_id_seq",sequenceName="mytable_id_seq", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="mytable_id_seq")
If you omit the allocationSize
then Hibernate assumes it's bizarre default of 50
and fails to check that the sequence actually increments by 50 so it tries to insert already-used IDs and fails. 如果您忽略了
allocationSize
那么Hibernate会认为它是默认值50
并且无法检查序列是否实际递增50,因此它尝试插入已使用的ID并失败。
Hibernate/JPA isn't able to automatically create a value for your non-id-properties. Hibernate / JPA无法自动为您的非id属性创建一个值。 The @GeneratedValue annotation is only used in conjunction with @Id to create auto-numbering
@GeneratedValue批注仅与@Id结合使用以创建自动编号
Hibernate caches query results. Hibernate 缓存查询结果。
Notice the "as num", looks like hibernate is altering the SQL as well.注意“as num”,看起来 hibernate 也在改变 SQL。
You should be able to tell Hibernate not to cache results with您应该能够告诉 Hibernate 不要缓存结果
query.setCacheable(false);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.