在mybatis中,动态语句是个非常强大和灵活的功能,并且动态语句可以放在sql的任何地方,利用该功能,我们可以写出非常灵活的代码。在mybatis的动态语句中常常可能会用到以下几个运算和逻辑判断符:
① “!=” : 表示不等于
② “=”:表示等于。注意是一个等号。
③ “and” : 逻辑与(小写)
④ “or” : 逻辑或(小写)
【1】if元素
该元素是我们经常会用到的,常用语判断传入的某个参数是否为null或者为某个指定的值,例如下面的语句。
<select id=”selectUsers” parameterType=”int” resultType=”User”>
select
user_id as "id",
user_name as "userName",
hashed_password as "hashedPassword"
from some_table
<if test="id != null and id!=''">
where id = #{id}
</if>
</select>
该语句的意思是判断参数id是否不为null以及不为空字符串,如果是则查询指定id的记录,不然查询全部的记录。元素里面的test属性,顾名思义就是测试的意思,即测试指定的表达式是否成立,test后面指定的参数为传入的参数。
【2】choose、when和otherwise
这3个元素是组合起用的,表达一种 if..else..的意义。
示例如下:
<select id=”selectUsers” parameterType=”int” resultType=”User”>
select
user_id as "id",
user_name as "userName",
hashed_password as "hashedPassword"
from some_table
<choose>
<when test="id != null">
where id = #{id}
</when>
<otherwise>
where id = '123'
</otherwise>
</select>
上面表达的意思是,如果参数id不为空,则查询指定id的记录,否则查询id为123的记录。这里只列举了一个when,其实可以连续的添加多个,但是otherwise只能有一个。
【3】trim、where、set
这3个元素主要功能就是帮助我们去除多余的关键字。where对应sql语句中的where关键字,set对应更新语句中的set关键字。
示例如下:
<select id="findActiveBlogLike"
parameterType="Blog" 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 title like #{author.name}
</if>
</select>
如果第1个if和第2个if条件成立,则形成的SQL为:
SELECT * FROM BLOG WHERE state=#{state} AND title like #{title}
如果第2个if和第3个if条件成立,则形成的SQL为:
SELECT * FROM BLOG WHERE AND title like #{title} AND title like #{author.name}
明显第二条语句是错误的。如果让我们自己来考虑到各种可能,那么在面对复杂的动态语句的时候,将会是非常头痛的事情,为此,mybatis框架为我们提供了更好的解决办法。
【3.1】trim元素
该元素的目的就是却掉前后执行的内容,其表达式如下:
<trim prefix="" prefixOverrides="" suffix="" suffixOverrides="" ></trim>
prefixOverrides:表示在trim包含的sql语句中,要被覆写的前缀,可以用”|”或者”||”来分割。
示例如下:
<trim prefixOverrides="and | or" ></trim>
// 这里面的and和or不区分大小写。
prefix:与prefixOverrides搭配使用,它们俩总是同时出现。该属性表示由prefixOverrides指定的前缀要被覆写成的内容-即 prefix 覆盖 prefixOverrides。
示例如下:
<trim prefix="" prefixOverrides="and | or" ></trim>
//表示把第一个and或者or变为空
<trim prefix="where" prefixOverrides="and " ></trim>
//表示把第一个and变为where
suffixOverrides和suffix和上面两个的规则是一样的,只是这两个是处理语句的最后,而上面两个是处理语句的最前。
把上面的例子改为下面的方式:
<select id="findActiveBlogLike" parameterType="Blog" resultType="Blog">
SELECT * FROM BLOG
<trim prefix="where" prefixOverrides="and | or">
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
<!-- 此处为完全匹配,可以选择使用模糊查询 !!! -->
<!--AND title like "%"#{name}"%" 或者
AND title like CONCAT('%','${name}','%')-->
</if>
<if test="author != null and author.name != null">
AND title like #{author.name}
</if>
</select>
此时如果条件1和条件2成立,则形成的SQL为:
SELECT * FROM BLOG where state = #{state} AND title like #{title}
可以发现,虽然state前面没有and或者or,但是trim会为语句加上where。
如果条件2和条件3成立,则形成的SQL为:
SELECT * FROM BLOG WHERE title like #{title} AND title like #{author.name}
这时,会把trim元素中的SQL语句的前缀AND变为where。
上面的效果和下面是一样的:
<select id="findActiveBlogLike" parameterType="Blog" resultType="Blog">
SELECT * FROM BLOG WHERE
<trim prefix="" prefixOverrides="and | or">
<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 title like #{author.name}
</if>
</select>
我们再加上对suffix的使用,示例如下:
<select id="findActiveBlogLike"
parameterType="Blog" resultType="Blog">
SELECT * FROM BLOG
<trim prefix="where" prefixOverrides="and | or" suffix="" suffixOverrides=",">
<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 title like #{author.name} ,
</if>
</select>
这时,如果条件3成立,会除掉最后的逗号”,”。
trim元素非常灵活,可以中在任何的位置,但由于我们在实际的使用中,where语句的后面和set语句的后面是最需要要处理的,所以mybatis又特意为我们定义了where元素和set元素。
【3.2】where元素
先举例如下:
<select id=”findActiveBlogLike”
parameterType=”Blog” 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 title like #{author.name}
</if>
</where>
如果第一个if不成立,第2个if才成立,那么where元素会去掉AND。
【3.3】set元素
set元素会动态前置SET关键字,而且也会消除任意无关的逗号。
<update id="updateAuthorIfNecessary" parameterType="domain.blog.Author">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
如果第一个条件不成立,那么会消除第一条语句后面的 “,”其他类同。
等价于如下:
<trim preffix="SET" suffixOverrides=","> .......</trim>
【4】foreach元素
foreach元素是非常强大的,它允许你指定一个集合,声明集合项和索引变量,它们可以用在元素体内。它也允许你指定开放和关闭的字符串,在迭代之间放置分隔符。这个元素是很智能的,它不会偶然地附加多余的分隔符。通常是构建在IN条件中的。
示例如下:
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
注意:你可以传递一个List实例或者数组作为参数对象传给MyBatis。当你这么做的时候,MyBatis会自动将它包装在一个Map中,用名称作为键。List实例将会以“list”作为键,而数组实例将会以“array”作为键。
① item=”item”:这里指定的是集合遍历的时候每个元素的名字,就好比为集合中的对象定义了一个名字,我们可以通过该名字来使用对象,这里的例子取名为“item”,我们可以随意的改名。如果这个名字指定的是一个对象,那么我们也可以这么使用:#{item.name},即访问对象中的name属性。
② collection=”list”:如果我们传递的参数是个对象,然后是要遍历对象中的某个集合,那么我们可以这么使用:collection=”param.list”,即:传入的参数名为param,该对象里面有个名为list的集合属性。
【5】使用foreach进行批量插入
示例如下:
insert into Author (username ,password ,email ) values
<foreach collection="list" item="item" index="index" separator="," >
(#{item.username},#{item.password},#{item.email })
</foreach>
MyBatis的批量操作参考博客:博客地址