jOOQ 的字段未在 SQL 中转换 {0}

jOOQ's field not converting {0} in SQL

我有一个这样声明的 jOOQ 字段(这是过度简化):

field("INTERVAL '{0} minutes'", Duration.class, X)

我希望生成一个 X 分钟的持续时间,我可以在我的查询中使用它,但它始终生成 0 分钟的持续时间。我用 toString 检查了生成的 SQL,我看到的不是预期的 INTERVAL '30 minutes' jOOQ 生成的 INTERVAL '{0} minutes',因此,它将 {0} 视为文字而不是替换它由模板变量。

我是这样测试的,这个:

using(configuration).select(field("INTERVAL '30 minutes'", Duration.class)).toString()

产量:

select INTERVAL '30 minutes'

而这个:

using(configuration).select(field("INTERVAL '{0} minutes'", Duration.class, 30)).toString()

产量:

select INTERVAL '{0} minutes'

是否有解决此问题的方法?

我用这个解决了我的问题:

field("INTERVAL '" + X + " minutes'", Duration.class)

如果您查看 jOOQ 文档 here,您会看到以下相关部分:

When processing these plain SQL templates, a mini parser is run that handles things like

  • String literals
  • ...

The above are recognised by the templating engine and contents inside of them are ignored when replacing numbered placeholders and/or bind variables.

因此,根据文档,预计引号内的 {0} 不会被替换。但对于使用 jOOQ 构建 Postgres 间隔的情况来说,这是非常出乎意料的,Postgres 只会吞下那个 {0} 并导致一个不会产生异常的错误,所以没有它的踪迹:

# select interval '{0} minutes';

 interval 
----------
 00:00:00
(1 row)

如您所示 , and as is documented for jOOQ's plain SQL templating feature,模板会预处理字符串文字(以及注释和其他一些内容),以防止修改它们。

But you should never resort to concatenating strings with jOOQ。总有更好的方法。你可以这样做,例如:

field("INTERVAL {0}", Duration.class, DSL.inline(X + " minutes"))

我知道。我还在连接字符串。但我在 "safe place" 中这样做,由 DSL.inline()(或 DSL.val())包装,它产生正确转义的文字(或绑定变量) .我的意思是永远不应该有理由连接 SQL 片段,即使是普通的 SQL 模板。