在开发过程遇到一个需求,查询筛选框中存在两种可传入字段:多选字段和手动输入,根据传入的字符串数组和手动输入对数据库的某个字段分别进行一次in的精确匹配和like模糊查询。
因为参数是动态传入的,开始拼装的sql语句如下
if(GETWAYLIST != null && ! GETWAYLIST.isEmpty() && GETWAY != null && GETWY != "")
sql="select * from HOUSE where 1=1 and GETWAY in (:GETWAYLIST) and GETWAY like :GETWAY";
GETWAYLIST = Arrays.asList(getWay.sprit(",")//传入的多选项,多个以逗号相隔
这样写的问题就是如果两个条件同时存在,其中一个查询为空会导致另外一个条件查询失败。
将上述的sql修改后的语句为
select * from HOUSE where 1=1 and GETWAY in (:GETWAYLIST) or GETWAY like :GETWAY;
但是sql中and的执行优先度比or的优先度高,先执行了前面的and逻辑再执行后面的or语句,所以查出来的数据并不是我想要的数据
最后查阅资料后修改语句为
select * from HOUSE where 1=1 and (GETWAY in (:GETWAYLIST) or GETWAY like :GETWAY);
()的优先度比and的要高。
另外项目中用到了springjpa的Specification方法拼装数据库查询方法,其中的写法如下(针对同一参数不同的查询类型)
public class HouseSpecification implements Specification
//筛选条件参数-证载用途
String proveUse;
//筛选条件参数-实际用途手动输入
String proveUseOther;
public HouseSpecification( String proveUse, String proveUseOther){
this.proveUse=proveUse;
this.proveUseOther=proveUseOther;
}
@SuppressWarnings("static-access")
@Override
public Predicate toPredicate(Root
{
//证载用途,根据传入参数拼装
if(!CheckUtil.isNullorEmpty(proveUse)&&!CheckUtil.isNullorEmpty(proveUseOther)){
List
predicates.add(cb.or(cb.and(root.
}
else if(!CheckUtil.isNullorEmpty(proveUse)&&CheckUtil.isNullorEmpty(proveUseOther)){
List
predicates.add(cb.and(root.
}
else if(!CheckUtil.isNullorEmpty(proveUseOther)){
predicates.add(cb.and(cb.like(root.
}
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}
}
使用时调用dao层封装好的 findAll(new HouseSpecification (proveUse,proveUseOther))