遇到了一个 JPA 查询的问题 ,我原来的JPA语句是这样的
@Query(value = " select s from SmsCountEntity s where (?1 is null or s.areaType in (?1)) order by s.dateCreate desc ")
Page findSmsCountPage( List areaList,Pageable pageable);
看了项目其他也是这样的写法,但还是报错了,喵喵喵?不科学啊。
"message": "org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: {vector} [ select new com.dfl.ycp3.enquiry.dto.SmsCountDTO(s.shopCode,s.shortName,s.areaType) from com.dfl.ycp3.enquiry.entity.SmsCountEntity s where (:x4_0, :x4_1, :x4_2 is null or s.areaType in (:x4_0, :x4_1, :x4_2)) order by s.dateCreate desc , s.id desc];
很明显我大概知道是入参的 List areaList 问题,因为 JPA 语句中会判断入参的 List areaList 是否为空,就是 ?1 is null ,但是加上去了在测试的时候就报错了。
去网上搜索,发生这种错误原因有这两种:
第一种
当将数组中的数据放在列表中且没有括号时,用于从列表中搜索数据库的查询语法将是错误的。
例如:
把 s.areaType in (?1) 写成 s.areaType in ?1
因为没把参入用括号括起来,会有语法错误。
第二种
用 coalesce 判断 null
例如:where (coalesce(?1, null) is null or s.areaType in (?1))
因为如果向量为空,则可以产生null;如果不是,则产生第一个值
显然我是第二种情况,诶,搞了我一早上,终于解决了!!!
修改后
@Query(value = " select new com.dfl.ycp3.enquiry.dto.SmsCountDTO(s.areaType) from SmsCountEntity s where (coalesce(?1, null) is null or s.areaType in (?1)) and (coalesce(?2, null) is null or s.cityCode in (?2)) order by s.dateCreate desc ")
Page findSmsCountPage( List areaList, Pageable pageable);
额外补充:
为什么这个 coalesce 这么神奇呢?
官方文档解释:
创建一个表达式,如果其所有参数的评估结果都为 null,则返回 null,否则返回第一个非 null 参数的值。