JPA SpEL可选List参数传多值触发SQLServer语法异常求助
问题原因
抛出SQLServerException的核心原因是IN子句的集合参数缺少括号包裹:
- 当status参数只传入单个值时,JPA的SpEL解析后会生成类似
e.distrstttypecode in 'VALID'的合法SQL,所以查询可以正常运行 - 当status传入多个值的集合时,SpEL直接将集合展开为逗号分隔的字面量,但你写的
in ?#{#requestdto.getStatus}没有给参数加括号,最终生成的SQL为e.distrstttypecode in 1,2,3,不符合SQL Server语法要求(IN后的多值列表必须放在括号内),数据库解析到逗号位置时就会抛出「需要布尔类型表达式、出现非布尔类型」的错误。
另外你贴的代码存在一处笔误:@Query(value = select distinct开头的SQL语句缺少起始双引号,实际运行时会直接编译报错,需要补上。
修复方法
- 给IN子句的集合参数外层补充括号,修正语法问题
- 补充空集合判断,避免传入空列表时生成
IN ()的非法SQL - 建议将参数占位符的
?#写法替换为JPA更兼容的:#命名参数写法,减少SpEL解析异常
修正后的完整查询代码如下:
@Query(value = "select distinct a.invn, a.accid, ac.accountCode, b.Fbusinesscode" + ", b.scode, i.invtype, d.dtid, d.did " + " from INV.BINv a " + "join READONLY.Fbusiness b on a.FbusinessId =b.FbusinessId " + "join READONLY.Acc ac on a.accid=ac.accid " + "join INV.Doc c on a.invid = c.invid " + "join INV.Dstreq d on c.docid = d.docid " + "join INV.dassoc e " + "on d.dassocId = e.dassocId " + "join BLNG.InvMType AS i on e.invtypeId = i.invtypeId "+ "where (:#{#requestdto.invoiceNumber} is null OR a.InvoiceEntityNumber = :#{#requestdto.invoiceNumber}) and " + " (:#{#requestdto.mod} is null OR i.InvTypeName = :#{#requestdto.mod}) and " + " (:#{#requestdto.getStatus() == null || #requestdto.getStatus().isEmpty()} OR e.distrstttypecode in (:#{#requestdto.getStatus()})) " )
补充说明
如果你的DTO中status字段是public属性可直接访问,把上面代码里的#requestdto.getStatus()替换成#requestdto.status即可,核心要保证IN后面的集合参数被括号包裹。
内容的提问来源于stack exchange,提问作者ramkr
相关产品推荐
相关产品推荐

