Mybatis动态SQL
在mybtis中动态sql主要用到的几个节点元素有:
1、if
2、choose(when, otherwise)
3、trim(where, if)
4、foreach
if的用法
- 用法: if的用法较为简单,对一些条件做出判断,条件成立则执行,不成立则跳过。
- 例子 当我们数据字段较多时,这是就会出现许多搜索条件,但在搜索时并不是所有的搜索条件,因此在写sql语句时就需要我们判断某些条件是否为空,如果为空就不执行该字段的查询。
<select id="queryStudentsByLikesAdmin" parameterType="map" resultType="map">
SELECT student.no,student.name,student.gender,direction.name direction,profession.name profession,classes.name
classesName
FROM t_student student
LEFT JOIN (SELECT id, name FROM t_direction) direction ON direction.id = student.direction_id
LEFT JOIN (SELECT id,name FROM t_profession) profession ON profession.id = student.profession_id
LEFT JOIN (SELECT id,name FROM t_classes) classes ON classes.id = student.classes_id
<where>
<if test="level!=''">
and student.level = ${level}
</if>
and student.no LIKE #{studentNo}
<if test="directionId!=''">
and direction_id =#{directionId}
</if>
<if test="professionId!=''">
AND profession.id = #{professionId}
</if>
<if test="classesId!=''">
AND student.classes_id = #{classesId}
</if>
and student.name
LIKE #{name}
</where>
</select>
choose(when, otherwise)的用法
- 用法:choose when 主要在多个条件的情况下只满足其中一个条件的应用场景中使用,例如这里就构建一个query条件,分别传递id,name与createTime。假设我们查询Visitor表时,如果VisitorId有值则,使用Id查询,如果VisitorName有值则采用VisitName查询
- 例子:
<!-- 满足其中一个条件时候用choose when操作 -->
<select id="getListChooseWhenDemo" resultMap="visitorRs"
parameterType="BasicQueryArgs">
<include refid="getListSqlConditions" />
<where>
<if test="queryStatus>0">
status=#{queryStatus}
</if>
<choose>
<when test="queryId!=0">
and id=#{queryId}
</when>
<when test="queryName!=null">
and name like #{queryName}
</when>
<otherwise>
and createTime>= #{queryTime}
</otherwise>
</choose>
</where>
</select>
- 在这里说一下<include>的用法,在mybatis中<sql>用来封装SQL语句, <include>来调用。简单例子:
//<sql>封装sql语句
<sql id="select">
select * from T_name
</sql>
<sql id="desc">
order by T_name.name DESC
</sql>
//<include>调用封装好的sql语句
<select id="find" resultType="*">
<include refid="select" />
<include refid="desc" />
</select>
- 上面这段代码的意思就是查询T_name表中的全部信息,然后按照字段"name"进行排序。
where if (trim)的用法
- where关键词的好处是在于,如果有相应的过滤条件的话,它知道在适当的时候插入where关键词。而且它也知道在何时该去掉相应的AND与OR的连接符
- 例子
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
WHERE
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>
不会因为所有条件不满足变为
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
WHERE
</select>
或者因为没有满足第一个条件,单单满足后面的条件变成
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
WHERE
AND title like ‘someTitle'
</select>
- set trim和上面的where一样,set和trim也是智能标记
- 例子
<update id="updateUserSet" parameterType="User">
update User
<set>
<if test="userName != null">userName=#{userName},</if>
<if test="password != null">password=#{password},</if>
</set>
where id=#{id}
</update>
如果两个条件都不为空,那么实际执行的sql语句为:
update User SET userName=?, password=? where id=?
set 自动识别并把sql语句中第二个逗号去掉的。
- trim标识为格式化标识,可以与其他标识完成where和set的功能
prefix 前缀增加 suffix 后缀增加 prefixOverrides 自动判断前置 suffixOverrides 自动判断后置
<update id="updateUserTrim" parameterType="User">
UPDATE User
<trim prefix="SET" suffixOverrides="," suffix="WHERE id = #{id}" >
<if test="userName != null and userName != '' ">
userName = #{userName},
</if>
<if test="password != null and password != '' ">
password=#{password},
</if>
</trim>
与上面的set语句对比,prefix="SET" 是为SQL语句设置前缀,suffixOverrides是自动判断后缀 "," suffix="WHERE id = #{id}" 是自动在加上后缀。
如果password和userName都有值,则该条sql语句为:
UPDATE User SET userName = ?, password=? WHERE id = ?
foreach的用法
foreach元素的属性主要有 item,index,collection,open,separator,close。
item
循环体中的具体对象。支持属性的点路径访问,如
item.age,item.info.details。 具体说明:在list和数组中是其中的对象,在map中是value。 该参数为必选。
collection
要做foreach的对象,作为入参时,List<?>对象默认用list代替作为键,数组对象有array代替作为键,Map对象用map代替作为键。 当然在作为入参时可以使用@Param("keyName")来设置键,设置keyName后,list,array,map将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子: 如果User有属性List ids。入参是User对象,那么这个collection = "ids" 如果User有属性Ids ids;其中Ids是个对象,Ids有个属性List id;入参是User对象,那么collection = "ids.id" 上面只是举例,具体collection等于什么,就看你想对那个元素做循环。 该参数为必选。
separator
元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。
index
在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选。
open
foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选。
close
foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。
需要注意一下collection不同情况下的用法
- 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
- 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
- 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可
相关案例:
<select id="countByUserList" resultType="_int" parameterType="list">
select count(*) from users
<where>
id in
<foreach item="item" collection="list" separator="," open="(" close=")" index="">
#{item.id, jdbcType=NUMERIC}
</foreach>
</where>
</select>
![Uploading fc7388015ca53d2bbc8d4309f8527919_785719.jpg . . .]
上面的sql语句等价与
select count(*) from users WHERE id in ( ? , ? )
传入map类型的参数时:
<insert id="ins_string_string">
insert into string_string (key, value) values
<foreach item="item" index="key" collection="map"
open="" separator="," close="">(#{key}, #{item})</foreach>
</insert>
表中需要两个值,正好和K,V对应,因而map中的一个K,V就对应一条数据,如果map中有多个K,V,就会保存多个结果
对应的sql语句为:
insert into string_string (key, value) values (?, ?) , (?, ?)