mybatis if else if 条件判断SQL片段表达式取值和拼接
前言
最近在开发项目的时候涉及到复杂的动态条件查询,但是mybaits本身不支持if elseif类似的判断但是我们可以间接通过 chose when otherwise 去实现其中choose为一个整体 when是if otherwise是else
快速使用
以前我们进行条件判断时候使用if标签进行判断,条件并列存在
<if test="seat_no != null and seat_no != '' ">
AND seat_no = #{seat_no}
</if>
现在 使用chose when otherwise条件只要有一个成立,其他的就不会再判断了。如果没有成立的条件则默认执行otherwise中的内容
<choose>
<when test="……">
……
</when>
<otherwise>
……
</otherwise>
</choose>
以下是我自己真实使用的例子,并且经过了测试,仅供参考:
根据动态条件筛选查询用户信息
<select id="findUsersByUser" resultType="cn.soboys.kmall.sys.entity.User">
select tu.USER_ID,tu.USERNAME,tu.SSEX,td.DEPT_NAME,tu.MOBILE,tu.EMAIL,tu.STATUS,tu.CREATE_TIME,
td.DEPT_ID
from t_user tu left join t_dept td on tu.DEPT_ID = td.DEPT_ID
<where>
<choose>
<when test="userParams.adminType==4">
and tu.ADMIN_TYPE_ID in(2,3)
</when>
<otherwise>
<include refid="search"></include>
</otherwise>
</choose>
</where>
</select>
<sql id="search">
<if test="userParams.adminType==null or userParams.adminType==''">
and tu.ADMIN_TYPE_ID in(0,1)
</if>
<if test="userParams.adminType != null and userParams.adminType != ''">
and tu.ADMIN_TYPE_ID=#{userParams.adminType}
</if>
<if test="userParams.roleId != null and userParams.roleId != ''">
and (select group_concat(ur.ROLE_ID)
from t_user u
right join t_user_role ur on ur.USER_ID = u.USER_ID,
t_role r
where r.ROLE_ID = ur.ROLE_ID
and u.USER_ID = tu.USER_ID and r.ROLE_ID=#{userParams.roleId})
</if>
<if test="userParams.mobile != null and userParams.mobile != ''">
AND tu.MOBILE =#{userParams.mobile}
</if>
<if test="userParams.username != null and userParams.username != ''">
AND tu.USERNAME like CONCAT('%',#{userParams.username},'%')
</if>
<if test="userParams.ssex != null and userParams.ssex != ''">
AND tu.SSEX =#{userParams.ssex}
</if>
<if test="userParams.status != null and userParams.status != ''">
AND tu.STATUS =#{userParams.status}
</if>
<if test="userParams.deptId != null and userParams.deptId != ''">
AND td.DEPT_ID =#{userParams.deptId}
</if>
<if test="userParams.createTime != null and userParams.createTime != ''">
AND DATE_FORMAT(tu.CREATE_TIME,'%Y%m%d') BETWEEN substring_index(#{userParams.createTime},'#',1) and substring_index(#{userParams.createTime},'#',-1)
</if>
</sql>
这里就用到啦 if else if 判断。 choose标签中when条件一但不成立,就会执行otherwise标签中的条件,判断语句,也就是我下面包含的sql片段条件
更详细的条件标签使用参考我这一篇文章点击进入
SQL片段拼接
我们再写sql语句的时候往往会有这样一些要求,一些重复的sql语句片段,我们不想重复去写,那么可以通过sql片段方式去抽离,公共sql然后在需要的地方去引用
MyBatis 中 <sql> 元素用于定义一个 SQL 片段,用于分离一些公共的 SQL 语句,例如:SELECT 关键字和 WHERE 关键字之间的部分。其中:
id:唯一标识符,用于在其他地方使用 <include> 标签引用;
lang:设置字符编码;
databaseId:指定执行该 SQL 语句的数据库ID,数据库ID在 mybatis-cfg.xml 中的 中配置。
同时,你也能够看见 <sql> 标签中可以使用<include>、<trim>、<where>、<set>、<foreach>、<choose>、<if>、<bind>等标签定义复杂的 SQL 片段
简单使用定义sql片段如下:
<sql id="user_columns">
`user_id`, `name`, `sex`, `age`
</sql>
在 <sql> 标签中使用 <include> 标签引入定义的sql片段,如下:
<!-- 定义基础列 -->
<sql id="user_base_columns">
`user_id`, `name`
</sql>
<!-- 定义一个SQL片段 -->
<sql id="user_columns">
<include refid="user_base_columns"/>, `sex`, `age`
</sql>
场景使用案例如:查询用户信息
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hxstrive.mybatis.sql.demo1.UserMapper">
<!-- 映射结果 -->
<resultMap id="RESULT_MAP" type="com.hxstrive.mybatis.sql.demo1.UserBean">
<id column="user_id" jdbcType="INTEGER" property="userId" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="sex" jdbcType="VARCHAR" property="sex" />
<result column="age" jdbcType="INTEGER" property="age" />
</resultMap>
<!-- 定义一个SQL片段 -->
<sql id="user_columns">
`user_id`, `name`, `sex`, `age`
</sql>
<!-- 查询所有用户信息 -->
<select id="findAll" resultMap="RESULT_MAP">
select <include refid="user_columns" /> from `user`
</select>
</mapper>
SQL参数取值和OGNL表达式
看到我们上面去值参数通过#{params}这种方式来去值的其中传进来的参数 #{xx} 就是使用的 OGNL 表达式。
Mybatis 官方文档中「XML 映射文件」模块里边,有解析到:
说当我们使用 #{} 类型参数符号的时候,其实就是告诉 Mybatis 创建一个预处理语句参数,通过 JDBC,这样的一个参数在 SQL 中会由一个 "?" 来标识,并传递到一个新的预处理语句中。


也就是说当我们使用 #{XX} OGNL 表达式的时候, 它会先帮我们生成一条带占位符的 SQL 语句,然后在底层帮我们设置这个参数:ps.setInt(1, id);
OGNL 是 Object-Graph Navigation Language 的缩写,对象-图行导航语言,语法为:#{ }。
是不是有点懵,不知道这是个啥?
OGNL 作用是在对象和视图之间做数据的交互,可以存取对象的属性和调用对象的方法,通过表达式可以迭代出整个对象的结构图
MyBatis常用OGNL表达式如下:

上述内容只是合适在MyBatis中使用的OGNL表达式,完整的表达式点击这里。
MyBatis中可以使用OGNL的地方有两处:
- 动态
SQL表达式中 ${param}参数中
如下例子MySql like 查询:
<select id="xxx" ...>
select id,name,... from country
<where>
<if test="name != null and name != ''">
name like concat('%', #{name}, '%')
</if>
</where>
</select>
上面代码中test的值会使用OGNL计算结果。
例二,通用 like 查询:
<select id="xxx" ...>
select id,name,... from country
<bind name="nameLike" value="'%' + name + '%'"/>
<where>
<if test="name != null and name != ''">
name like #{nameLike}
</if>
</where>
</select>
这里的value值会使用OGNL计算。
注:对<bind参数的调用可以通过#{}或 ${} 方式获取,#{}可以防止注入。
在通用Mapper中支持一种UUID的主键,在通用Mapper中的实现就是使用了标签,这个标签调用了一个静态方法,大概方法如下:
<bind name="username_bind"
value='@java.util.UUID@randomUUID().toString().replace("-", "")' />
这种方式虽然能自动调用静态方法,但是没法回写对应的属性值,因此使用时需要注意。
${params}中的参数
上面like的例子中使用下面这种方式最简单
<select id="xxx" ...>
select id,name,... from country
<where>
<if test="name != null and name != ''">
name like '${'%' + name + '%'}'
</if>
</where>
</select>
这里注意写的是${'%' + name + '%'},而不是%${name}%,这两种方式的结果一样,但是处理过程不一样。
在MyBatis中处理${}的时候,只是使用OGNL计算这个结果值,然后替换SQL中对应的${xxx},OGNL处理的只是${这里的表达式}。
这里表达式可以是OGNL支持的所有表达式,可以写的很复杂,可以调用静态方法返回值,也可以调用静态的属性值。
例子,条件判断入参属性值是否包含子字符串可以直接使用 contains判断
<foreach collection="list" item="item" index="index" separator="AND" open="(" close=")">
<choose>
<when test='item.cname.contains("select") or item.cname.contains("checkbox") or item.cname.contains("date")'>
<if test='item.cname.contains("select") or item.cname.contains("checkbox")'>
find_in_set(#{item.value},base.${item.cname})
</if>
<if test='item.cname.contains("date")'>
DATE_FORMAT(base.${item.cname},'%Y-%m-%d') = DATE_FORMAT(#{item.value},'%Y-%m-%d')
</if>
</when>
<otherwise>
base.${item.cname} = #{item.value}
</otherwise>
</choose>
</foreach>
mybatis if else if 条件判断SQL片段表达式取值和拼接的更多相关文章
- SQL利用Case When Then多条件判断SQL 语句
http://www.cnblogs.com/kevin2013/archive/2010/07/02/1769682.html SQL利用Case When Then多条件判断SQL ,用于sele ...
- sql中#与$取值
在mapper.xml中#与$都是用来取值的 <update id="addUrl"> update user_power set url = #{newurl} wh ...
- 关于mybatis中基本类型条件判断问题
零:sql动态语句中经常会有根据数据库某个字段状态进行判断的 如:status=0为未激活,status=1为激活的,那搜索未激活时: <if test="model.activeSt ...
- 多重条件判断SQL:用于用户名称,密码,权限的检测和判断
string sqlstr = "select count(*) from tb_admin where 用户名='"+UserName+"'and 密码='" ...
- python 条件判断的三元表达式
示例:求两数中最大者 在JavaScript中代码如下: x = 1; y = 2; console.log(x > y ? x : y) 在python中代码如下: # 条件为真时的返回结果 ...
- Sql server 函数--取值年月
GetDate()是获取当前时间 1.例如获取年月类似 201706 需要改为语句: Select Datename(year,GetDate())+Datename(month,GetDate())
- SpringBoot使用Mybatis注解开发教程-分页-动态sql
代码示例可以参考个人GitHub项目kingboy-springboot-data 一.环境配置 1.引入mybatis依赖 compile( //SpringMVC 'org.springframe ...
- if 条件判断
逻辑判断的布尔值(true&false) 1.逻辑值(bool)用来表示诸如:对与错,真与假,非于空等概念. 2.逻辑值包含了两个值:--true:表示非空的量(比如:string,tuple ...
- Perl if条件判断
Perl 条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. 条件判断常用: True #布尔值 not True #布尔值 ! True ...
随机推荐
- Beescms V4.0_R_20160525代码审计笔记
写在前面 什么是报错注入?正常用户访问服务器发送id信息返回正确的id数据.报错注入是想办法构造语句,让错误信息中可以显示数据库的内容:如果能让错误信息中返回数据库中的内容,即实现SQL注入. 复现过 ...
- noip模拟44[我想我以后会碰见计数题就溜走的]
noip模拟44 solutions 这一场抱零的也忒多了,我也只有45pts 据说好像是把几套题里面最难的收拾出来让我们考得 好惨烈啊,这次的考试我只有第一题骗了40pts,其他都抱零了 T1 Em ...
- Django 反向解析 request CBV
正则路径中的分组 无名分组 分组的概念:就是给某一段正则表达式用小括号括起来 无名分组按位置传参数,一一对应. view中除去request,其他形参数量要与urls中分组数量一致. 无名分组就是将括 ...
- Spring Data JPA:解析SimpleJpaRepository
源码 SimpleJpaRepository的定义如下: /** * Default implementation of the {@link org.springframework.data.rep ...
- Spring详解(十)加载配置文件
在项目中有些参数经常需要修改,或者后期可能会有改动时,那我们最好把这些参数放到properties文件中,在源代码中读取properties里面的配置,这样后期只需要改动properties文件即可, ...
- HuaWeiJava 上机
1 /* 2 * 第二题,输入字符串长度,字符串,计数m.从前往后计数,当数到m个元素时,m个元素出列,同时将该元素赋值给m, 3 * 然后从下一个数计数循环,直到所有数字都出列,给定的数全部为大于0 ...
- PyQt4制作GUI
时间:2018-11-30 记录:byzqy 标题:PyQt4入门学习笔记(一) 地址:https://www.cnblogs.com/chuxiuhong/p/5865201.html 标题:PyQ ...
- 剖析虚幻渲染体系(11)- RDG
目录 11.1 本篇概述 11.2 RDG基础 11.2.1 RDG基础类型 11.2.2 RDG资源 11.2.3 RDG Pass 11.2.4 FRDGBuilder 11.3 RDG机制 11 ...
- Session原理、生命周期及购物车功能的实现
在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下).因此,在需要保存用户数据(保存该浏览器(会话)的相关信息)时 ...
- Linux系统的vsftpd服务配置
概述: FTP ( 文件传输协议 ) 是 INTERNET 上仍常用的最老的网络协议之一 , 它为系统提供了通过网络与远程服务器进行传输的简单方法FTP 服务器包的名称为 VSFTPD , 它代表 V ...