如何让 JOOQ 在 IN 子句中使用数组

5

我希望JOQ可以生成... in (?)并将列表绑定为数组参数(Postgres)。我的代码如下:

.where(
   Tables.TABLE.FIELD.in(idsList)
)
  1. 我该怎么做?
  2. 为什么不默认完成这个任务呢?既然生成字符串in(?,?,?,?,...)并由PG解析更有效率。

看起来你可能只在in子句中使用了几个id,但如果你要处理数百个id,请考虑创建一个批量id表。请考虑这一点,因为你永远不知道用户何时会选择数百个不同的项目(例如,想想Gmail复选框)。 - Adam Gent
1个回答

7

我该怎么做?

你可以使用 DSL.any(T[]) 操作符,例如:

TABLE.FIELD.eq(any(1, 2, 3))

这将仅将一个数组变量绑定到JDBC语句中。

为什么默认情况下不这样做,因为它比生成(和由PG解析)字符串更有效

也许值得考虑在设置中添加一个标志。我已经为此注册了一个功能请求:https://github.com/jOOQ/jOOQ/issues/6029

一般来说,jOOQ允许用户编写他们想要发送到数据库服务器的SQL,因此自动“优化”和重写SQL可能会对某些用户产生意外效果。这只是jOOQ的一般规则。始终值得考虑优化并通过设置使其成为可选项。

注意过早优化!

然而,实际测量这些东西总是很重要的。虽然使用您建议的方法确实减少了解析和SQL生成开销,但请注意,与硬编码的IN列表相比,数组的基数可能更难以正确估计。对于小列表使用数组可能会对执行计划产生负面影响。因此,您在解析器方面节省的几微秒将会抵消执行方面的几毫秒(?)!
我在以下博客文章中进行了基准测试: https://blog.jooq.org/sql-in-predicate-with-in-list-or-with-array-which-is-faster/ 在我的具体基准测试案例中,IN列表似乎始终优于数组版本,直到长度约为50。

如果您发布基准测试代码及其结果,这也会有所帮助。jOOQ是否提供对此类基准测试的支持?例如jOOQ-JMH之类的工具? - Dmitry Gusev
1
@DmitryGusev:添加了基准测试链接。它包含正在进行基准测试的SQL查询,以及在基准测试中使用的Sakila示例数据库的链接。使用jOOQ-JMH基准测试存根的有趣想法。我已经为此创建了一个功能请求:https://github.com/jOOQ/jOOQ/issues/6030。 - Lukas Eder
TABLE.FIELD.eq(DSL.any(1, 2, 3)) 上,我得到了 no suitable method found for in(QuantifiedSelect<Record1<Long>>) 错误。 - Alex Dvoretsky
嗯,你正在传递整数,但是你的方法期望长整型... 为什么不传递 1L, 2L, 3L 呢? - Lukas Eder
1
哦,是的,刚才意识到应该是“eq”而不是“in”。谢谢。 - Alex Dvoretsky
哦,是的,那肯定有帮助 :) - Lukas Eder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接