Mybatis的动态SQL基础使用
- 使用动态SQL完成多条件查询
- 使用if+where实现多余查询
- 使用 if+trim实现多条件查询
- 使用foreach完成复杂查询
- choose (when,otherwise)
- 总结
使用动态SQL完成多条件查询
动态SQL是Mybatis的一个强大的特性,在使用JDBC操作数据时,如果查询条件特别多,
那样将条件串联成SQL字符串是一件痛苦的事情,通常的解决方法是写很多if-else条件语句对字符串进行拼接,
但mybatis使用一种强大的动态SQL语言来改善这种情况,动态SQL基于OGNL表达式,
动态SQL的元素有
元素 | 说明 |
if | 利用if实现简单的条件选择 |
choose(when,otherwise) | 相当于Java中的switch语句,通常和when和otherwise搭配 |
where | 简化SQL语句中where的条件判断 |
set | 解决动态更新的语句 |
trim | 可以灵活地去除多余关键字 |
foreach | 迭代一个集合,通常用于in条件 |
使用if+where实现多余查询
- if
<select id="selectTest" resultType="Text" parameterType="string">
select id from text
<!-- name代表你传入参数的键值 -->
<if test="name!=null">
where name = #{name}
</if>
</select>
比如这是我们传入空值
得到的返回结果是
我在传值的是时候传入了一个null,在SQL映射文件他们进行了判断是否存在值,如果存在就按值进行查询,如果不存在就不执行if。
这个是我传入一个a为参数,查询出来的两条数据。
- while
假如查询条件为 id和name ,其中id 为空,name有值,或者id有值,name没值,则会查询结果显示不正确,
<select id="selectTest1" resultType="Text" parameterType="string">
select * from text where
<if test="id!=null">
id = #{id}
</if>
<if test="name!=null">
and name = #{name}
</if>
</select>
比如 这样编写的SQL语句,如果第一个id为null的话,SQL在后台运行出来的样子是这样的,
SELECT * FROM text where and name ='1'
查询起来
SELECT * FROM text where and name ='1'
[Err] 1064 - You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version
for the right syntax to use near 'and name ='1'' at line 1
这个意思讲 你 and name =1 的前要跟一个条件
如果 二个参数都为null的话,
SELECT * FROM text where
[Err] 1064 - You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version
for the right syntax to use near '' at line 1
报错的意思是讲你的语法出现了错误,使用where后后面必须要跟有一个条件,
这些错误 有一个简单的解决方法 就是 if 前面跟一个 where 1=1 就可以解决一部分问题了,但是我们有一个更好的方法使用 where 元素
<select id="selectTest1" resultType="Text" parameterType="string">
select * from text
<where>
<if test="id!=null">
id = #{id}
</if>
<if test="name!=null">
and name = #{name}
</if>
</where>
</select>
使用where 元素进行查询,两个条件都为空
log4j中显示的SQL语句
当 name = a ,id 为空时显示的SQL语句
where 元素主要用于简化 where 条件判断 ,并能智能化处理 and 和 or不必要担心关键字导致的语法错误,当他只有一个参数的 会自动 剔除条件前面的and 关键字 或者 or 关键字,如果两个if判断都为不通过, 它会自动剔除 where 。
使用 if+trim实现多条件查询
在mybatis中除了使用 if+where实现多条件查询,还有一个更为灵活的元素trim 可以替代 之前的做法
trim元素也会自动识别其标签内是否有返回值,若有返回值,会在自己包括的内容全面加上某些前缀,可以可以加入某些后缀,与之对应的属性是 prefix 和suffix ,也可把包含内容的首部某些内容覆盖(即忽略),也可以吧尾部某些内容覆盖,与之对应的是 prefixOverrides和suffixOverrides;
正因为trim有这样强大的功能,我们可以使用trim替代where 元素,并实现和where相同的效果
<select id="selectTest1" resultType="Text" parameterType="string">
select * from text
<trim prefix="where" prefixOverrides="and|or">
<if test="id!=null">
id = #{id}
</if>
<if test="name!=null">
and name = #{name}
</if>
</trim>
</select>
属性 | 说明 |
prefix | 前缀,作用是通过自动识别是否有返回值,在trim包含的内容加上前缀就像上面的trim |
suffix | 后缀,作用是在trim包含的内容上加上后缀 |
prefixOverrides | 对于trim包含内容的首部进行指定内容(如此处的 and 和 or )的省略 |
suffixOverrides | 对于trim包含内容的尾部进行指定内容的忽略 |
if+trim实现多条件查询
<!-- 使用if+trim实现多条件查询 -->
<select id="selectTestS" resultType="Text" parameterType="string">
select * from text
<!-- 设置前缀默认为where trim会自动判断是否有返回值,
有返回值,自动省略and或or 自动加上where前缀
suffix的使用方法和prefix差不多
-->
<trim prefix="where" prefixOverrides="and|or">
<if test="id!=null">
and id =#{id}
</if>
<if test="name!=null">
and name#{name}
</if>
</trim>
</select>
至于查询结果和上面的where+if相同
使用if+set改造更新操作
<!-- 使用if+trim改造更新操作 -->
<update id="updateText" parameterType="text">
update text<set>
<if test="name!=null">
name=#{name},
</if>
<if test="password!=null">
password=#{password},
</if>
<if test="userid!=null">
userid=#{userid}
</if>
</set>
where id = #{id}
</update>
我传入3个参数
这是执行生成的SQL语句,根据传入参数的个数生成更改参数个数,
set元素主要用于更新操作,它的主要功能和where元素差不多,主要是在包括的语句前生成一个set,若包含的语句是以逗号结束的,会自动把逗号忽略掉,在配合if元素可以动态地更新需要修改的字段,
使用trim+if代替set语句
<!-- 使用if+trim改造更新操作 -->
<update id="updateText" parameterType="text">
update text
<trim prefix="set" suffixOverrides="," suffix="where id = #{id}">
<if test="name!=null">
name=#{name},
</if>
<if test="password!=null">
password=#{password},
</if>
<if test="userid!=null">
userid=#{userid},
</if>
</trim>
</update>
运行结果和if+set一致,
使用foreach完成复杂查询
- Mybatis传入参数为数组类型的foreach迭代
//创建一个参数为integer类型的数组
public List<Text> getTextList(Integer[] roleIds);
编写SQL映射文件
<select id="getTextList" resultType="Text">
select * from text where id in
<foreach collection="array" item="roleIds" open="(" separator="," close=")">
#{roleIds}
</foreach>
</select>
我传入参数为 integer [] array = {1,2,3,4,5,6}时运行代码查询结果
属性 | 说明 |
item | 表示集合中每一个进行迭代时的别名 |
index | 指定一个名称,用于表示在迭代过程中,每次迭代到的位置 |
open | 表示该语句以什么开始 |
separator | 表示每次迭代之间以什么符号作为分隔符 |
close | 表示该语句以什么结束 |
collection | 最关键并容易出错的属性,如果参数为list的时候 属性值为list,如果参数为数组时,属性值为 array,如果参数为多参数的话,就必须把它封装为一个Map进行处理 |
参数类型为 list时
<select id="getTextList" resultType="Text">
select * from text where id in
<foreach collection="list" item="roleIds" open="(" separator="," close=")">
#{roleIds}
</foreach>
</select>
参数为Map比如
Map<String,Object> hasmap = new HashMap<String,Object>();
hasmap.put("id",1);
List<Integer> list = new ArrayList<Integer>();
hasmap.put("listage",list);
SQL映射文件格式为
<select id="getTextList" resultType="Text">
select * from text where id in
<!-- collection由于集合在 map的key为listage里面所以要读取自己输入list的key值 -->
<foreach collection="listage" item="roleMap" open="(" separator="," close=")">
#{roleMap}
</foreach>
</select>
choose (when,otherwise)
对于某些查询需求,虽有多个查询条件,但是我们不想应用所有的条件,只想选择其中一种情况下的查询结果,其中和java中switch相似。
<select id="selectTest1" resultType="Text" parameterType="string">
select * from text where 1=1
<choose>
<when test="id!=null">
and id = #{id}
</when >
<when test="name!=null">
and name = #{name}
</when >
<when test="password!=null">
and password= #{password}
</when >
<otherwise>
<!-- 查询全部 -->
</otherwise >
</choose>
</select>
属性 | 说明 |
when | 当其test属性条件满足的时候,就会输出when元素中的内容 |
otherwise | 当when中的所有条件不满足的时候,就会自动输出otherwise元素中的内容 |
总结
- 其实 mybatis的使用很简单,它的功能很强大,可以满足我们日常需求也可以做出很强大的功能
- mybatis 的只需要导入 一个jar包 功能强大 内存占用低