sql优化:当无法判断查询条件是否为空时也可以使用的sql语句
最近,使用java+mybatis开发时,遇到了一个情况:想执行一条sql语句从数据库查询数据,但是无法确定传入的参数是否为空。通过百度,发现了以下几种解决方法,在此整理如下。
其中,第3种解决办法最简洁高效。
1.根据参数是否为空,进行sql拼接。
例如,可以根据ID从数据库中查询数据,但是ID可能为空,此时则返回表中所有的数据。
代码大致如下:
String id = (String)req.getParameter("id");//从页面获得id
String sql = "select * from User where 1=1";//sql语句,方便拼接
//如果id不为空
if(!StringUtils.isBlank(id)){
sql=sql+"and id="+id;
}
之后如果有多个条件,也可以这样判断并拼接,最后执行该sql语句即可。
2.使用多条sql语句实现
由于项目中使用了注解的方式编写sql,因此不适用第一种解决方法,无法拼接sql。此时可以使用笨办法,使用多条sql语句实现功能。
例如,可以根据ID从数据库中查询数据,但是ID可能为空,此时则返回表中所有的数据。
代码大致如下:
UserMapper.java:
//注解1,查找表中所有数据
@Select("select * from User")
ArrayList<User> selectFromUser();
//注解2,根据id查找表中数据
@Select("select * from User where id=#{id}")
ArrayList<User> selectFromUserById(String id);
///
Service.java:
//java代码,根据id是否为空决定调用哪个方法
@Autowired
private UserMapper mapper;//注入mapper对象
public ArrayList<User> selectFromUser(String id){
if(StringUtils.isBlank(id)){
return mapper.selectFromUser();
}else{
return mapper.selectFromUserById(id);
}
}
3.对sql语句进行优化,使用sql语句实现
实际使用中,我发现前2种方法都不是很方便,当无法判断是否为空的参数变多时,都会导致代码量增多,给阅读与编写带来难度。后来,我在网上寻找更好的方法时,终于找到了只用1条sql语句就可以解决这个问题的方法,因此将整个代码记录如下,亲测可用。
使用第3种方法需要注意3点:
(1)我使用的是java+springboot+mybatis,注解方式的sql,因此只测试了注解方式可以实现,其它环境并没有测试。
(2)注解方式中,如果传入的参数过多,会导致"Mybatis错误:Parameter 'XXX' not found.",此时需要使用@Param注解指明参数与sql语句的对应关系。(代码中已使用)
(3)代码的第二个sql方法中,包含了使用between查询时间范围内数据的方法,在java中调用时对参数进行了一些修改,例如当时间范围为空时设置开始时间为"1999年",结束时间为"2999年"等类似的方法,因此sql可能不是很完善。
整个代码如下(Mapper.java):
import OrderBean;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Date;
@Mapper
@Component
public interface CompleteOrderMapper {
@Select("select * from completeOrder where (order_id = #{order_id} or #{order_id}='')" +
"and (prod_id = #{prod_id} or #{prod_id}='')" +
"and (amt = #{amt} or #{amt}='')" +
"and (buy_time like #{buyTime} or #{buyTime}='')")
ArrayList<OrderBean> selectBuyCompleteOrderWithBuyTime(@Param("order_id")String order_id, @Param("prod_id")String prod_id,@Param("amt")String amt, @Param("buyTime")String buyTime);
@Select("select * from completeOrder where (order_id = #{order_id} or #{order_id}='')" +
"and (prod_id = #{prod_id} or #{prod_id}='')" +
"and (amt = #{amt} or #{amt}='')" +
"and ((buy_time between #{beginTime} and #{endTime}) or #{beginTime} Is Null)")
ArrayList<OrderBean> selectBuyCompleteOrderWithRangeTime(@Param("order_id")String order_id,@Param("prod_id")String prod_id,@Param("amt")String amt,@Param("beginTime")Date beginTime, @Param("endTime")Date endTime);
}
说明:
这是个mapper接口,使用之前需要spring注入。
OrderBean是JavaBean对象,自己创建的。
原理:
1.select * from 表 where (字段=条件 or 条件=' ');
当条件不为空时:select * from 表 where 字段=条件;
当条件为空时:select * from 表 where ' '=' ';
具体原理可查看:https://blog.csdn.net/qq_39651858/article/details/81738199
2.使用@Param注解,解决Mybatis错误:Parameter 'XXX' not found.
具体细节可查看:https://blog.csdn.net/w86440044/article/details/29363067/ ,在这个网址的末尾位置有正确的用法。
在此感谢以上作者的文章。
本文到此结束,如有错误,欢迎各位读者批评指正,谢谢!