触发额外查询以获取序列下一个值-spring JPA

Posted

技术标签:

【中文标题】触发额外查询以获取序列下一个值-spring JPA【英文标题】:Extra query getting triggered for fetching sequence next value - spring JPA 【发布时间】:2020-12-25 14:52:48 【问题描述】:

我有一个主键列从 oracle 序列中获取值的表。如果我在表中插入一条记录,最好的方法是 -

INSERT INTO TABLE VALUES(SCHEMA.SEQUENCE.NEXTVAL, value1, value2, value3)

但是,当我使用 JPARepository 中的保存方法时,在创建对象时运行一个仅获取 SCHEMA.SEQUENCE.NEXTVAL 的选择查询,然后在事务结束时运行一个额外的 INSERT 查询。

SELECT SCHEMA.SEQUENCE.NEXTVAL FROM DUAL

INSERT INTO TABLE VALUES(val_from_select_query, value1, value2, value3)

这导致几乎双倍的时间。有没有办法配置我的实体,使其在插入查询中获取序列值,从而导致总体上只有 1 次往返数据库?

【问题讨论】:

【参考方案1】:

序列的增量是多少? 因为这只发生在您在增量边界内插入的第一行。

假设增量为 50,当您插入多个值(即使有延迟)时,您会看到:

SELECT SCHEMA.SEQUENCE.NEXTVAL FROM DUAL
INSERT INTO TABLE VALUES(val_from_select_query, value1, value2, value3)
INSERT INTO TABLE VALUES(val_from_select_query+1, value1, value2, value3)
INSERT INTO TABLE VALUES(val_from_select_query+2, value1, value2, value3)
...
INSERT INTO TABLE VALUES(val_from_select_query+48, value1, value2, value3)
INSERT INTO TABLE VALUES(val_from_select_query+49, value1, value2, value3)
SELECT SCHEMA.SEQUENCE.NEXTVAL FROM DUAL
INSERT INTO TABLE VALUES(val_from_select_query2, value1, value2, value3)
INSERT INTO TABLE VALUES(val_from_select_query2+1, value1, value2, value3)
...

我通常通过create sequence a_sequence_name start with 1 increment by 50 将增量设置为 50。 然而,这会导致 ids (1, 2, 3, 4, 5, 6, 7, 51, 52, 101) 出现一些差距,例如重新启动应用程序时。

【讨论】:

我必须根据收到的请求在表中插入 n 条记录。所以,我不能总是增加 50。此外,我放了一个循环并创建了 10 个对象并为每个对象调用 save。在这种情况下,select 和 insert 语句仍然被触发了 10 次。 您不必总是递增 50,它只是数据库中序列的设置。 Hibernate 会询问“当前起点”,然后它知道它可以填充接下来的 50 个 id,所以它不会再询问了。您是说您放置了一个循环来创建 10 个对象,并且 select 被调用了 10 次-您是否忘记将 DB 序列更改为增加 50(或任何其他大于 1 的数字)?这不必与您的“批次”相匹配 - 因为这些东西往往是动态的(例如,每个请求都不同)。【参考方案2】:

使用 ID 生成策略GenerationType.AUTO,JPA(或者更确切地说是底层 ORM 框架)需要知道生成的 ID,以便它可以在创建的对象上设置它。由于 INSERT 语句不返回 ID,因此需要额外的 SELECT。

在 Oracle 12 上,您可以使用 GenerationType.IDENTITY,这将产生一条语句:

INSERT INTO <TABLE> (...) values (?) RETURNING <PRIMARY_KEY> INTO ? 

【讨论】:

以上是关于触发额外查询以获取序列下一个值-spring JPA的主要内容,如果未能解决你的问题,请参考以下文章

用于从序列生成 id 的 Oracle 触发器的 HIbernate 问题

序列化表单为json对象,datagrid带额外参提交一次查询 后台用Spring data JPA 实现带条件的分页查询

oracle 序列视图索引

MySQL 触发器 - 使用额外值更新关系表

获取序列当前值

使用 GraphQL 查询获取最大值和最小值