Mybatis框架(十三)Mybatis的动态SQL

MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。

虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。

动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
本测试使用的数据库是book表:
在这里插入图片描述
注:创建maven项目、导包过程不做介绍。

  • if标签
  • choose标签
  • set标签
  • trim标签
  • SQL片段
  • foreach标签

一、if标签。
动态SQL通常要做的事情是有条件地包含where子句的一部分。所以在MyBatis中,元素是最常用的元素。它类似于Java中的if语句。
if标签用来实现根据条件拼接sql语句,下面示例用来判断参数如果不为null,则拼接sql。
下面来测试元素,具体过程如下:

  • 添加SQL映射语句
  • 添加数据操作接口方法
  • 调用数据操作接口方法
  • 测试动态SQL语句

1、在BookMapper.xml文件中,添加如下的SQL映射语句。

<!--    查找书籍-->
    <select id="queryBookIF" parameterType="map"  resultType="com.wst.pojo.Book">
        select * from book where 1=1
        <if test="bookname!=null">
            and bookname=#{bookname}
        </if>
        <if test="type!=null">
            and type=#{type}
        </if>
    </select>

2、在BookMapper接口中,添加如下数据操作接口的方法。

 //查询书籍
    List<Book> queryBookIF(Map map);

3、编写MyTest的测试类及操作接口的方法。

   public void queryBookIF(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        HashMap map = new HashMap();
        map.put("bookname","java");
        map.put("type","1");
        List<Book> books = mapper.queryBookIF(map);
        for (Book book : books) {
            System.out.println(book);
        }
        sqlSession.close();
    }

4、运行进行测试。

注意:当但是上面的SQL语句中如果传入的参数bookname为NULL的时候,则解析出错误的语句:select * from book where and type=#{type},看到这个SQL语句明显的就知道了语句的错误,为了解决这个问题,这里引入了where标签。
当 bookname 值为 null 时,查询语句会出现 “where and” 的情况,解决该情况除了将"where"改为“where 1=1”之外,还可以利用 where标签。这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以 AND 或 OR 开头的,则它会自动的去掉。
于是改写了上面的例子,增加了where标签如下:

<!--    查找书籍-->
    <select id="queryBookIF" parameterType="map"  resultType="com.wst.pojo.Book">
        select * from book
        <where>
            <if test="bookname!=null">
                and bookname=#{bookname}
            </if>
            <if test="type!=null">
                and type=#{type}
            </if>
        </where>
    </select>

二、choose标签 (when, otherwise)
有些时候,不想用到所有的条件语句,而只想从中择其一二。针对这种情况,MyBatis 提供了choose元素,它有点像Java中的 switch 语句。

  • 该标签类似于 Java 中的 switch、case、default。
  • choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。
  • 当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql语句。
    示例:
    数据库接口:
 List<Book> queryBookChoose(Map map);

SQL映射语句:

<!--    Choose的使用-->
    <select id="queryBookChoose" parameterType="map" resultType="com.wst.pojo.Book">
        select * from book
        <where>
            <choose>
                <when test="bookname != null">
                    and bookname=#{bookname}
                </when>
                <when test="type!=null">
                    and type = #{type}
                </when>
                <otherwise>
                    and count = #{count}
                </otherwise>
            </choose>
        </where>
    </select>

注:若我们同时添加bookname和type的值,最终的SQL也只会添加第一个属性值。

        map.put("bookname","java");
        map.put("type","1");

则只会添加第一个属性的值bookname!

三、set标签。
在动态update语句中,可以使用元素动态的更新列。set元素主要是用在更新操作的时候,主要是在包含的语句前输出一个set,然后如果包含的语句被逗号结束的话将会把该逗号去掉,如果set包含我们的内容为空的话发生错误。有了set元素我们就可以动态的更新那些修改了的列。
数据库接口:

  int updateBook(Map map);

SQL映射语句:

<!--    更新书的信息-->
    <update id="updateBook" parameterType="map">
        update book
        <set>
            <if test="bookname != null">
                bookname = #{bookname},
            </if>
            <if test="type != null">
                type = #{type},
            </if>
        </set>
        where id = #{id}
    </update>

四、trim元素
元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOverrides;正因为元素有这样的功能,所以也可以非常简单地利用来代替元素的功能。
trim元素有以下四个属性:

  • prefix:前缀
  • prefixOverrides:去掉第一个and或者是or
  • suffix:后缀
  • suffixOverrides:去掉最后一个逗号,也可以是其他的标记
<where>标签对应的trim实现:
<trim prefix="WHERE" prefixOverride="AND |OR ">
<set>标签对应的trim实现:
<trim prefix="SET" suffixOverrides=",">

数据库接口:

  List<Book> selectBookByTrim(Map map);

SQL映射语句:

	<select id="selectBookByTrim"  resultType="com.wst.pojo.Book" parameterType="map">
		select * from book
		<trim prefix="where" prefixOverrides="and |or">  
	        <if test="bookname !=null and bookname!=''">  
	            and bookname like concat('%',#{bookname},'%')
	        </if>  
	        <if test="type !=null and type!=''">  
	            and type = #{type} 
	        </if>    
    		</trim>  
	</select>

五、SQL片段
在mybatis中通过使用SQL片段可以提高代码的重用性,下面是一个具体的实例:
数据库接口:

 //查询书籍
    List<Book> queryBookIF(Map map);

SQL映射语句:

<!--    查找书籍-->
    <sql id="select-book">
        <if test="bookname!=null">
                        and bookname=#{bookname}
                    </if>
                    <if test="type!=null">
                        and type=#{type}
                    </if>
    </sql>

    <select id="queryBookIF" parameterType="map"  resultType="com.wst.pojo.Book">
        select * from book
        <where>
            <include refid="select-book"></include>
        </where>
    </select>

六、foreach 元素
元素主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach元素的属性主要有item,index,collection,open,separator,close。

  • item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中,每次迭代到的位置。
  • open表示该语句以什么开始。
  • separator表示在每次进行迭代之间以什么符号作为分隔符。
  • close表示以什么结束。
    在使用时,最关键的也是最容易出错的是collection属性,该属性是必选的,但在不同情况下,该属性的值是不一样的,主要有以下3种情况:
    如果传入的是单参数且参数类型是一个List的时候,collection属性值为list。
    如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array。
    如果传入的参数是多个时,需要把它们封装成一个Map,当然单参数也可以封装成Map。Map的key是参数名,collection属性值是传入的List或array对象在自己封装的Map中的key。
    实例:
    数据库接口:
    List<Book> queryBookForeach(Map map);

SQL映射语句:

  <select id="queryBookForeach" parameterType="map" resultType="com.wst.pojo.Book">
        select * from book

        <where>
            <foreach collection="ids" item="id" open="(" close=")" separator="or">
                id = #{id}
            </foreach>
        </where>
    </select>
发布了105 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43759352/article/details/104611612
今日推荐