i-Report 5.6.0参数传递异常求助:硬编码正常但传参结果不符
这种情况我之前也碰到过,核心原因大多是参数类型不匹配或者JasperReports处理参数的逻辑和你预期的不一样,给你几个具体的排查和解决方向:
优先检查参数的定义类型
你硬编码写1,3,4,8,10,11,12,17,18,22时,数据库会把它当成多个数字ID的列表,但如果你的$P{collectedStudentIds}参数被定义成字符串类型,实际执行SQL时会变成:s.id not in ('1,3,4,8,10,11,12,17,18,22')这相当于让数据库判断
s.id是否不等于这个完整的字符串,而不是不等于列表里的每个数字,结果自然和硬编码不一致。
正确的做法是把参数类型改成java.util.List(或java.util.Collection),然后把SQL里的$P{collectedStudentIds}改成$P!{collectedStudentIds}——这里的!是告诉Jasper直接把集合里的元素展开成逗号分隔的列表,而非作为单个参数绑定。验证实际执行的SQL语句
你可以开启JasperReports的SQL日志,或者在报表里临时加个文本框输出$P{collectedStudentIds}的内容和类型,对比硬编码和传参时实际执行的SQL差异。比如如果传参后的SQL里参数值带了引号、空格或者格式错误,就能直接定位问题。处理空参数的边界情况
如果这个参数有可能为空,not in子句会出现逻辑问题(因为not in (null)会返回空结果),建议在SQL里补充判断逻辑:where 1=1 and ($P{collectedStudentIds} is null or s.id not in ($P!{collectedStudentIds})) order by cn.id, s.id这样当参数为空时,不会过滤任何学生ID。
如果必须用字符串参数的替代方案
要是因为某些限制只能用字符串类型的参数,可以改用数据库的字符串分割函数实现逻辑,比如MySQL里可以这样写:where 1=1 and FIND_IN_SET(s.id, $P{collectedStudentIds}) = 0 order by cn.id, s.id不过这种方式性能不如
not in,只适合数据量不大的场景,同时要注意SQL注入风险。
内容的提问来源于stack exchange,提问作者Sumon Bappi

