You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JDBI执行SQL被截断引发PostgreSQL类型错误的原因是什么

问题原因
  1. @Define 占位符无法在SQL单引号内生效
    JDBI 中 @Define 注解的作用是做SQL模板的字符串替换,默认规则下解析器不会识别单引号包裹内容中的 <占位符> 标记。你代码中将 <timeInterval> 写在 INTERVAL '<timeInterval>' 的单引号内部,导致占位符没有被实际传入的参数替换,原样保留在了待执行的SQL中。
  2. 特殊字符触发SQL截断
    未被替换的 <timeInterval> 起始的 < 字符会被JDBI的模板解析器识别为占位符起始标记,因为没有匹配的结束标记,解析逻辑直接丢弃了该符号之后的所有SQL内容,最终生成的执行SQL到 AND modification_date 就结束了。
    此时WHERE条件的最后一段相当于 AND modification_date,modification_date 是时间戳类型,不符合PostgreSQL要求的「AND关键字后面必须接布尔表达式」的语法规则,所以抛出了你看到的异常。
修复方案

你可以选择任意一种方式修改:

  • 方案1:将单引号移到占位符外侧,保证 @Define 能正常识别占位符
@Override
@SqlQuery("SELECT * FROM " + TABLE_NAME + " WHERE " + COLUMN_CAMPAIGN_ID + " = :campaignId AND " + COLUMN_STATUS
                + " = 0 AND " + COLUMN_STAGE_ID + " IS NULL AND " + COLUMN_MODIFICATION_DATE
                + " < NOW() - INTERVAL <timeInterval>")
List<Idea> getDraftIdeasBeforeTime(@Bind("campaignId") long campaignId,
                @Define("timeInterval") String timeInterval);

调用方法时传入的 timeInterval 参数需要自带单引号,例如 getDraftIdeasBeforeTime(campaignId, "'7 days'")。

  • 方案2:改用类型转换写法,直接绑定参数更安全
@Override
@SqlQuery("SELECT * FROM " + TABLE_NAME + " WHERE " + COLUMN_CAMPAIGN_ID + " = :campaignId AND " + COLUMN_STATUS
                + " = 0 AND " + COLUMN_STAGE_ID + " IS NULL AND " + COLUMN_MODIFICATION_DATE
                + " < NOW() - CAST(:timeInterval AS INTERVAL)")
List<Idea> getDraftIdeasBeforeTime(@Bind("campaignId") long campaignId,
                @Bind("timeInterval") String timeInterval);

该方案不需要用 @Define,直接用 @Bind 传参即可,还能避免SQL注入风险。

内容的提问来源于stack exchange,提问作者Aakash Verma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 09:36:06