JDBI SQL模板if条件报错:Undefined attribute for token '<endif>'排查
Undefined attribute for token '<endif>'异常 使用JDBI框架时触发org.jdbi.v3.core.statement.UnableToCreateStatementException异常,提示信息为Undefined attribute for token '
Dao接口方法
@RegisterRowMapper(MapMapper.class) @SqlQuery( "SELECT Table1.tenantId,Table1.sacTenantId, sacLogId,currentStep,status from Table1 inner join Table2 on Table1.tenantId = Table2.tenantId where <if(tenantId)>Table1.tenantId = :tenantId and<endif> Table2.status = 'FAILED'" ) List<Map<String, Object>> getTenantFailedJobDetails(@Define("tenantId") @Bind("tenantId") String tenantId);
错误追踪信息
"level":"ERROR","categories":[],"msg":"Servlet.service() for servlet
[dispatcherServlet] in context with path [] threw exception [Request
processing failed; nested exception is
org.jdbi.v3.core.statement.UnableToCreateStatementException: Error
rendering SQL template: 'SELECT Table1.tenantId,Table1.sacTenantId,
sacLogId,currentStep,status from Table1 inner join Table2 on
Table1.tenantId = Table2.tenantId where <if(tenantId)>Table1.tenantId
= :tenantId and Table2.status = 'FAILED'' [statement:"null", arguments:{positional:{0:DUMMY-TENANT}, named:{tenantId:DUMMY-TENANT},
finder:[]}]] with root
cause","stacktrace":["org.jdbi.v3.core.statement.UnableToCreateStatementException:
Undefined attribute for token '' [statement:"null",
arguments:{positional:{0:DUMMY-TENANT}, named:{tenantId:DUMMY-TENANT},
finder:[]}]"
问题原因与修复方案
核心问题
你混淆了JDBI与其他ORM框架(如MyBatis)的模板语法:JDBI的SQL模板中,<if>标签的闭合标记是</if>,而非<endif>。<endif>是MyBatis的专属语法,JDBI无法识别该标记,因此抛出“未定义属性”的异常。
修复后的代码
将<endif>替换为</if>即可解决异常:
@RegisterRowMapper(MapMapper.class) @SqlQuery( "SELECT Table1.tenantId,Table1.sacTenantId, sacLogId,currentStep,status from Table1 inner join Table2 on Table1.tenantId = Table2.tenantId where <if(tenantId)>Table1.tenantId = :tenantId and</if> Table2.status = 'FAILED'" ) List<Map<String, Object>> getTenantFailedJobDetails(@Define("tenantId") @Bind("tenantId") String tenantId);
额外优化建议
当前SQL逻辑在tenantId为空时会正常渲染为where Table2.status = 'FAILED',但如果后续调整条件顺序,可能出现多余的and。可以将固定条件前置,或者使用<if>包裹整个可变条件块并包含and,避免语法隐患:
@SqlQuery( "SELECT Table1.tenantId,Table1.sacTenantId, sacLogId,currentStep,status from Table1 inner join Table2 on Table1.tenantId = Table2.tenantId where Table2.status = 'FAILED' <if(tenantId)>and Table1.tenantId = :tenantId</if>" )
内容的提问来源于stack exchange,提问作者Saqib Hussain

