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实现多余查询

  1. if
<select id="selectTest" resultType="Text" parameterType="string">
        select id from text
        <!-- name代表你传入参数的键值 -->
        <if test="name!=null">
            where name = #{name}
        </if>
    </select>

比如这是我们传入空值

mysql 语句sql中where 后面跟 if 表达式可以是 in 语句吗 sql where 后面加判断_java


得到的返回结果是

mysql 语句sql中where 后面跟 if 表达式可以是 in 语句吗 sql where 后面加判断_SQL_02


我在传值的是时候传入了一个null,在SQL映射文件他们进行了判断是否存在值,如果存在就按值进行查询,如果不存在就不执行if。

mysql 语句sql中where 后面跟 if 表达式可以是 in 语句吗 sql where 后面加判断_mysql_03


这个是我传入一个a为参数,查询出来的两条数据。

mysql 语句sql中where 后面跟 if 表达式可以是 in 语句吗 sql where 后面加判断_mysql_04

  1. 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 元素进行查询,两个条件都为空

mysql 语句sql中where 后面跟 if 表达式可以是 in 语句吗 sql where 后面加判断_Text_05


log4j中显示的SQL语句

mysql 语句sql中where 后面跟 if 表达式可以是 in 语句吗 sql where 后面加判断_SQL_06


当 name = a ,id 为空时显示的SQL语句

mysql 语句sql中where 后面跟 if 表达式可以是 in 语句吗 sql where 后面加判断_SQL_07


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个参数

mysql 语句sql中where 后面跟 if 表达式可以是 in 语句吗 sql where 后面加判断_mybatis_08


这是执行生成的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完成复杂查询

  1. 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}时运行代码查询结果

mysql 语句sql中where 后面跟 if 表达式可以是 in 语句吗 sql where 后面加判断_mybatis_09

属性

说明

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元素中的内容

总结

  1. 其实 mybatis的使用很简单,它的功能很强大,可以满足我们日常需求也可以做出很强大的功能
  2. mybatis 的只需要导入 一个jar包 功能强大 内存占用低