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/  ,在这个网址的末尾位置有正确的用法。

   

  在此感谢以上作者的文章。

  本文到此结束,如有错误,欢迎各位读者批评指正,谢谢!

posted @ 2018-12-25 17:13  codeToSuccess  阅读(682)  评论(0编辑  收藏  举报