动态SQl是MyBatis的一个强大的特性,在使用JDBC操作数据时,如果查询条件特别多,将条件串联成SQL字符串是一件痛苦的事情,通常的解决方法是写很多的if-else条件语句对字符串进行拼接, 并确保不能忘了空格在字段的最后省略都好,MyBatis使用一种很强大的动态SQL语言来改善这种情形.动态SQL基于OGNL的表达式,可使我们方便地在SQL语句中实现某些逻辑.用于实现动态SQL的元素如下.

  • if:利用if实现简单的条件选择.
  • choose(when,otherwise):相当于Java中的switch语句,通常与when和otherwise搭配.
  • when:简化SQL语句中的where条件判断
  • set:解决动态更新语句
  • 可以灵活地去除多余的关键字
  • foreach:迭代一个集合,通常用于in条件;

1使用if+where实现多条件查询

(1)if

在该实例中,采用的是封装User对象入参,进行查询.

/*** 查询用户列表* @param userName* @param userRoId* @return*/public List<User> getUsersList(@Param("userName")String userName,@Param("userRole")Integer userRoId);
}

在上述代码中使用了@Param注解,并将参数roleId重名名为userRole,故UserMapper.xml的代码如下:

<!-- 查询用户列表 --><select id="getUserList" resultMap="userList">select u.*,r.roleName as userRoleName from smbms_user u,smbms_role r where u.userRole = r.idand u.userName like CONCAT('%',#{userName},'%')and u.userRole =#{userRole}</select><!-- userList映射 --><resultMap type="cn.smbms.pojo.User" id="userList"><result property="id" column="id"/><result property="userCode" column="userCode"/><result property="userName" column="userName"/><result property="phone" column="phone"/><result property="birthday" column="birthday"/><result property="gender" column="gender"/><result property="userRole" column="userRole"/><result property="userRoleName" column="userRoleName"/></resultMap>

完成修改后运行调试类,首先测试2个条件给均给出的情况测试方法,部分代码如下

     int roleId=3;String userName="孙";List<User> users=sqlSession.getMapper(UserMapper.class).getUserList(userName,roleId);for (User user : users) {System.out.println("userName: "+user.getUserName()+" userRole: "+user.getUserRoleName());}

运行效果如下:


然后模拟用户没有输入所有条件的情况下,如传入的用户角色roleId参数为空,即只按用户名称进行模糊查询,测试方法如下

@Testpublic  void getUserList() {// TODO Auto-generated method stubSqlSession sqlSession=MyBatisUtil.createSqlsession();int roleId=3;String userName=null;List<User> users=sqlSession.getMapper(UserMapper.class).getUserList(userName,roleId);for (User user : users) {System.out.println("userName: "+user.getUserName()+" userRole: "+user.getUserRoleName());}}

运行效果如下:

通过该运行效果可以发现,查询列表为空,根据业务需求,用户并不会完整地输入所有的查询条件,因此用于这只用情况使用动态SQL的if元素来实现,具体实现代码如下:

 <!-- 查询用户列表 -->
<select id="getUserList" resultMap="userList">SELECT u.*,r.roleName FROM smbms_user u,smbms_role r WHERE u.userrole=r.id<if test="userRole!=null">and u.userRole=#{userRole}</if><if test="userName!=null and userName!=''">and u.userName like CONCAT('%',#{userName},'%')</if></select><!-- userList映射 --><resultMap type="cn.smbms.pojo.User" id="userList"><result property="id" column="id"/><result property="userCode" column="userCode"/><result property="userName" column="userName"/><result property="phone" column="phone"/><result property="birthday" column="birthday"/><result property="gender" column="gender"/><result property="userRole" column="userRole"/><result property="userRoleName" column="roleName"/></resultMap>

运行效果如下:

(2)where

改造上面的示例,需求为:根据用户名称(模糊查询)和角色id查询用户列表,但是用户列表不需要显示角色名称.修改示例代码,只需要将UserMapper.xml中的getUserList的select的返回值类型改为resultType,并修改SQL,代码如下:

// TODO Auto-generated method stubSqlSession sqlSession=MyBatisUtil.createSqlsession();int roleId=3;String userName=null;List<User> users=sqlSession.getMapper(UserMapper.class).getUserList(userName,roleId);System.out.println("userSize: "+users.size());for (User user : users) {System.out.println("userName: "+user.getUserName()+" userRole: "+user.getUserRoleName());}}

然后进行测试,测试方法代码片段如下:

         int roleId=3;String userName=null;List<User> users=sqlSession.getMapper(UserMapper.class).getUserList(userName,roleId);System.out.println("userSize: "+users.size());for (User user : users) {System.out.println("userName: "+user.getUserName()+" userRole: "+user.getUserRoleName());}}

运行效果如下:

通过运行结果,发现后台报错,具体错误为SQL语句错误即while后面多了一个and;
where元素主要是用来简化SQL语句中的where条件判断,并能智能的处理and和or,不必担心多余关键字导致的语法错误.下面通过一个示例演示,修改UserMapper.xml代码如下:

<select id="getUserList" resultType="User">SELECT * FROM smbms_user<where><if test="userName!=null and userName!=''">userName like CONCAT('%',#{userName},'%')</if><if test="userRole!=null">and userRole=#{userRole}</if></where></select>

通过上述代码,where元素标签会自动识别其标签内是否有返回值,若有,就插入一个where,此外,若该便签的内容是以and或者or开头的,会自动剔除.下面根据以上两种出错情况分别进行运行调试;
> 第一种情况,参数userName传入空字符串(或者null),参数roleId给定值,测试方法代码片段如下:

// TODO Auto-generated method stubSqlSession sqlSession=MyBatisUtil.createSqlsession();int roleId=3;String userName=null;List<User> users=sqlSession.getMapper(UserMapper.class).getUserList(userName,roleId);System.out.println("userSize: "+users.size());for (User user : users) {System.out.println("userName: "+user.getUserName()+" userRole: "+user.getUserRoleName());}}

运行效果如下:

通过上图可知控制台输出的SQL语句根据传递的参数进行了正确拼接,where子句里自动剔除了"and"
>第二种情况:两个参数传入的值均为空,测试方法代码片段如下:

         Integer roleId=null;String userName="";List<User> users=sqlSession.getMapper(UserMapper.class).getUserList(userName,roleId);System.out.println("userSize: "+users.size());for (User user : users) {System.out.println("userName: "+user.getUserName());}

运行效果如下:

通过上图可知运行正确如下,控制台输出的日志SQL语句同样传递的参数进行了正确拼接,由于此种情况下没有参数所以自动去除where;
其实这些方法都很麻烦,下面介绍一个简单的方法
>重点就是在userMapper.xml文件里面修改里面的代码

在sql语句中加入where 1 =1 ,后面直接用if标签判断值是否为空,这样就能避免where标签不能去除,已经多余的and无法剔除;
同样的测试下代码:

         //userName为空Integer roleId=3;String userName="";List<User> users=sqlSession.getMapper(UserMapper.class).getUserList(userName,roleId);System.out.println("userSize: "+users.size());for (User user : users) {System.out.println("userName: "+user.getUserName());}

测试结果如下:

测试结果可知去除了roleId的那段代码;
接下来测试当userName为空的时候,测试代码如下:


由上面的日志文件可知,自动剔除了userName的那段代码;
看到这个时候不要生气,不要时候为啥不直接说这个,简单的方法,学习从来没有简单方法,要一步一步走过来,也只有坚持到最后的人,才能看到这个方法

使用动态SQL完成多条件查询相关推荐

  1. SAP ABAP 动态内表的条件查询(SORT / READ TABLE / LOOP)

    SAP ABAP 动态内表的条件查询(SORT / READ TABLE / LOOP) 简介: 动态内表是动态报表的核心,动态内表的条件操作能有效解决性能问题.这篇文章用于普及动态内表在 SORT ...

  2. SQL语句之条件查询--WHERE(where)

    SQL语句之条件查询–WHERE(where) 语法表示 select 查询列表 from表名 where筛选条件 筛选条件分类: 筛选方式 运算符类型 运算符 一,按条件表达式筛选 条件运算符 &g ...

  3. mybatis学习(四)连接池、事务、动态SQL、多表查询

    目录 连接池 事务 动态SQL 1.if标签 2.where标签 3.foreach标签 4.sql标签 多表操作 (一)一对多.多对一 .一对一 1.查询所有账户,在账户信息后显示所属的用户的用户名 ...

  4. 动态SQL的 if 条件判断

    错误方式一: 在mybatis的动态sql语句中使用<if>标签可以判断sql中的条件是否成立. <select id="getPerson" resultTyp ...

  5. 动态SQL,单表查询

    mybatis动态SQL语句 简单的单表增删改查配上动态SQL mapper接口(通过OrderId查询订单,返回集合) List selectByOrderId(Integer orderId); ...

  6. SQL语句多条件查询

    SQL多条件查询中如果有and和or,and的优先级高于or,如果不加括号会先运行and,然后再运行or 数据表 一.查询时先且查询,则先and条件查询,查询结果与or后面的条件进行或查询 SQL语句 ...

  7. MySQL中SQL命令语句条件查询

    一.聚合函数 聚合函数:又叫组函数,用来对表中的数据进行统计和计算,结合group by分组使用,用于统计和计算分组数据 常用聚合函数 count(col):求指定列的总行数 max(col):求指定 ...

  8. SQL的多条件查询语句

    SELECT * FROM table_name WHERE 条件1 and 条件2: SELECT * FROM table_name WHERE 条件1 and 条件2 or 条件:SELECT ...

  9. 〖Python 数据库开发实战 - MySQL篇⑯〗- SQL 语句的条件查询

    万叶集

最新文章

  1. YOLOV5 v6.1更新 | TensorRT+TPU+OpenVINO+TFJS+TFLite等平台一键导出和部署
  2. tradingview Vue
  3. ARM NEON 优化
  4. 手把手 docker 从零搭建 jenkins 服务器
  5. VTK:Utilities之BoundingBoxIntersection
  6. oracle 产看执行计划_ODBA 技能SPM计划
  7. matlab的syntax简记
  8. x86-64函数调用参数传递
  9. 武器系统仿真技术(一):系统误差分析的蒙特卡洛算法
  10. 安装MYSQL出现checking for termcap functions
  11. k3修改wifi加密方式
  12. ubuntu美化--壁纸软件
  13. 利用Catmull-Rom算法画人脸轮廓
  14. 【总目录】人工智能、机器学习、深度学习总结大全----目录.未完待续...
  15. 计算机网络中的层次结构
  16. WEB集群实现LVS负载均衡+域名解析 经典案例——详解
  17. CAD属性编辑操作——回退、重作
  18. 关于定时器setTimeout与setInterval的定时与关闭操作
  19. 关于zigbee的一些术语
  20. Oracle如何查询大于1的结果,ORACLE的一些查询

热门文章

  1. 新买的路由器怎么设置(收藏)
  2. 实验 7——成员访问控制与异常
  3. 操作系统之文件管理:3、文件目录(文件控制块FCB、多级目录结构、无环图目录结构、索引节点)
  4. Spring和Spring Boot的区别
  5. 从C语言来理解文件系统
  6. js 获取url问号前_js获取历史url
  7. javaScript获取URL
  8. 滴滴打车推出的“专车服务”后的见闻以及思考
  9. Chrome扩展程序实现网页翻译
  10. 【图像压缩】超先验模型 《VARIATIONAL IMAGE COMPRESSION WITH A SCALE HYPERPRIOR》