SSM-动态SQL

SSM-动态SQL

动态SQL主要是解决同一类SQL语句匹配不同的问题,举个栗子:

加入我要执行一个查询语句,但是是一个不确定的查询语句,可能会根据ID去查,如果ID没有就可能根据名字去查,或者说同时根据两个去查。那么这时候SQL语句就是不确定的,就要用到mybatis动态SQL语句了,同时Mybatis是基于OGNL表达式的。

动态SQL语句

  • if
  • where
  • choose
    • when
    • otherwise
  • set
  • trim
  • foreach
  • sql
  • include
  • bind

数据形式

idthe_nameflower
1 小明 小红花

if

if很简单的知道,就是判断条件的。
xml映射文件配置文件

<!--动态SQL if语句-->
<select id="query1" resultType="com.weno.pojo.Girl">
    select * from Girl where
    <if test= "the_name != null">
        the_name = #{the_name}
    </if>
    <if test= "flower != null">
        and flower = #{flower};
    </if>
</select>
@Test
public void m006() {
    SqlSession sqlSession = MybatisUtil.getSession();

    GirlMapper mapper = sqlSession.getMapper(GirlMapper.class);

    Girl g= new Girl();

    g.setName("小明");
    // g.setFlower("小红花");
    Girl girl=mapper.query1(g);

    sqlSession.commit();
    sqlSession.close();
    System.out.printf(girl.toString());
}

如果此时我们将小红花注释掉查看一下运行结果:

DEBUG [main] - ==>  Preparing: select * from Girl where the_name = ? 
DEBUG [main] - ==> Parameters: 小明(String)
TRACE [main] - <==    Columns: id, the_name, flower
TRACE [main] - <==        Row: 1, 小明, 小红花
DEBUG [main] - <==      Total: 1

在SQL语句中并没有加上flower语句。但是此时却有一个问题,如果the_namenull,而flower不为null,那么在SQL语句中岂不是多了一个and,变成了:

DEBUG [main] - ==>  Preparing: select * from Girl where and flower = ?; 

这时候程序肯定报错,那么我们该如何处理呢?那么接下来说一下where标签。

where

任然使用上面的例子:

<select id="query2" resultType="com.weno.pojo.Girl">
    select * from Girl
    <where>
        <if test="the_name != null">
            and the_name = #{the_name}
        </if>
        <if test="flower != null">
            and flower = #{flower}
        </if>
    </where>
</select>

这个跟上面的区别就是将where改成了<where>标签。
<where>在这里的作用就是当标签中有返回值时,就插入一个where,同时,如果标签是以ANDOR【不区分大小写】开头时,就剔除。

choose

choose语句有点类似Java中的switch,当有一个符合时,就选择那一个并跳出。
映射文件

<select id="query3" resultType="com.weno.pojo.Girl">
    select * from Girl where
    <choose>
        <when test="id != null and id!=''">
            id = #{id}
        </when>
        <when test="the_name != null and the_name != ''">
            the_name = #{the_name}
        </when>

        <otherwise>
            flower = #{flower}
        </otherwise>
    </choose>
</select>

在这种情况下,如果id符合的话,就不会再考虑下面的了。

@Test
public void m008() {
    SqlSession sqlSession = MybatisUtil.getSession();
    GirlMapper mapper = sqlSession.getMapper(GirlMapper.class);
    Girl g= new Girl();
    g.setId(1);
    g.setName("小明");
    g.setFlower("小红花");
    Girl girl=mapper.query3(g);
    sqlSession.commit();
    sqlSession.close();
    System.out.printf(girl.toString());
}

SQL语句,在其中并没有选择the_name

DEBUG [main] - ==>  Preparing: select * from Girl where id = ? 

set

set是一个更新数据的标签

<update id="update1">
    update Girl set the_name=#{the_name},flower=#{flower} where id=#{id};
</update>

java代码:

@Test
public void m009() {
    SqlSession sqlSession = MybatisUtil.getSession();
    GirlMapper mapper = sqlSession.getMapper(GirlMapper.class);
    Girl g= new Girl();
    g.setId(1);
    g.setName("小红");
//        g.setFlower("小明花");
    mapper.update1(g);
    sqlSession.commit();
    sqlSession.close();
}

如果此时这样执行,那么在数据库表里面,flower的数据即为null。假如此时,使用if标签

<update id="update2">
    update Girl set
    <if test="the_name != null and the_name != ''">
    the_name=#{the_name},
    </if>
    <if test="flower != null and flower != ''">
        flower=#{flower}
    </if>
    where id=#{id};
</update>

那么此时会出现一个问题,如果第一个符合,而第二个不符合,那么就会多一个,,此时使用<set>标签就可以解决这个问题

<update id="update3">
    update Girl
    <set>
        <if test="the_name != null and the_name != ''">
            the_name=#{the_name},
        </if>
        <if test="flower != null and flower != ''">
            flower=#{flower},
        </if>
    </set>
    where id=#{id};
</update>

<set>标签和<where>有点类似,在<set>标签中,如果结尾有逗号,就将逗号去除。

trim

<trim>就很神奇了,它既可以实现<set>的功能,也能够实现<where>的功能。

trim可以在前面增加和删除内容,也可在在后面也执行此操作。

<update id="query0">
    <trim prefixOverrides="and | or">
        <if test="the_name != null">
            and the_name = #{the_name}
        </if>
        <if test="flower != null">
            and flower = #{flower}
        </if>
    </trim>
</update>

去除第一个and或则是or

  • prefix:前缀      
  • prefixoverride:去掉第一个a
  • suffix:后缀  
  • suffixoverride:去掉最后一个

foreach

foreach 类似for循环。

改写我们用 foreach 来改写 select * from Girl where id in (1,2,3)

映射文件

    <!-- collection:指定输入对象中的集合属性,使用@Param("ids")指令名字
        item:每次遍历生成的对象
        open:开始遍历时的拼接字符串
        close:结束时拼接的字符串
        separator:遍历对象之间需要拼接的字符串
        select * from Girl where id in (1,2,3) -->
<select id="queryByIDs" resultType="com.weno.pojo.Girl">
    select * from Girl where
    <foreach collection="ids" item="id" open="id in (" close=" ) " separator=",">
            #{id}
    </foreach>
</select>

sql

SQL片段主要是为了提高效率,可以讲动态SQL的判断部分独立处理,提高程序的复用率。

<!-- id是sql片段的标识,一定要唯一 -->
<sql id="sql_1"> 
  <if test="the_name != null and the_name != ''">
      the_name = #{the_name}
  </if>
</sql>

注意:在SQL片段中,不要包括where

include

引用SQL片段,使用上面的例子

<select id="query2" resultType="com.weno.pojo.Girl">
    select * from Girl
    <where>
        <include refid="sql_1"/>
        <if test="flower != null">
            and flower = #{flower}
        </if>
    </where>

就是如此简单。

bind

<bind>简单的来说,就是使值变成另外一个。

例如在模糊查询语句中要使传入的值变成%*%,那么就使用bind进行连接。

<select id="queryLikeByName" resultType="com.weno.pojo.Girl">
    select * from Girl
    <bind name="_name" value="'%'+the_name+'%'"/>
    <!-- 如果the_name代表A,那么_name则代表%A% -->
    where the_name like #{_name}
</select>

mybati的动态语句大概就这样了,如果学会了使用,那么毋庸置疑,可以大量的提高我们的效率。
不过更多的mybatis的使用,可以参考mybatis的 官方文档

妈耶,第一次写这么多的字,纪念一下!!

原文地址:https://www.cnblogs.com/xiaohuiduan/p/9867669.html