MyBatis知识六 动态SQL语句

MyBatis动态SQL语句的关键字有:
if
choose (when, otherwise)
trim (where, set)
foreach
等类型。

MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。
拼接sql语句的好处在于,可以进行选择性查询,如果不传递参数则是进行全部查询,如果有参数传递则是进行拼接到对应的sql上。
where 元素知道只有在一个以上的if条件有值的情况下才去插入“WHERE”子句。而且,若最后的内容是“AND”或“OR”开头的,where 元素也知道如何将他们去除。

IF

IF语句的使用通常是有条件的 进行SQL语句的Where条件的查询。所以注意【Where】标签的使用。

<select id="findUserList" parameterType="com.wf.model.UserVo" resultType="com.wf.model.UserExtends">
        select * from user
        <where>
        <if test="userExtends!=null">
            <if test="userExtends.sex!=null and userExtends.sex!=''">
                and user.sex=#{userExtends.sex}
            </if>
            <if test="userExtends.username!=null and userExtends.username!='' ">
                and user.username like '%${userExtends.username}%'
            </if>
        </if>
        </where>
    </select>

说明: 上述的SQL语句就是利用IF条件进行SQL语句的拼装,这里,利用IF标签的test属性进行条件的判断,如果条件成立,则进行SQL语句拼装,如果不成立则跳过此条件语句的拼装。
解释:当我们传入的条件UserVo为NULL时,则直接进行的语句为“select * from user”;
如果我们UserVo不为空时,然后我们又会分别判断我们的sex和username是不是为空或者null,如果都有值则会都进行拼接,此时的SQL语句为:“select * from user where user.sex = ‘参数一’ and user.username like ‘%参数二%’ ”;

choose(when, otherwise)

choose的使用,主要是在多个条件下进行选择匹配时使用,比如我们常说的在,两个中选其中的一个条件,它有点像 Java 中的 switch 语句,只进行匹配条件成功的语句进行拼接。

<select id="findUserListChoose" parameterType="com.wf.model.UserVo" resultType="com.wf.model.UserExtends">
        select * from user 
        <where>
            <choose>
                <when test="userExtends.sex!=null and userExtends.sex!=''">
                    user.sex=#{userExtends.sex}
                </when>
                <when test="userExtends.username!=null and userExtends.username!=''">
                    and user.username like '%${userExtends.username}%' 
                </when>
                <otherwise>
                    and 1=1
                </otherwise>
            </choose>
        </where>
    </select>

说明:上述的SQL则是在进行条件匹配,如果when标签的条件进行匹配成功,那么就进行拼接SQL语句,如果所有的when条件都不成立的情况下,则是进行otherwise匹配。

trim (where, set)

自定义 trim 元素是用来定制我们想要的功能。
1、由于我们的where元素知道只有在一个以上的if条件有值的情况下才去插入“WHERE”子句。而且,若最后的内容是“AND”或“OR”开头的,where 元素也知道如何将他们去除。
这样的话,我们可以利用我们的trim元素进行等价转化。

<!-- trim 语法  -->
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
      ... 
    </trim>


<!-- trim 配置 -->
    <select id="findUserListtrim" parameterType="com.wf.model.UserVo" resultType="com.wf.model.UserExtends">
        select * from user
        <trim prefix="where" prefixOverrides="AND |OR |String">
        <if test="userExtends!=null">
            <if test="userExtends.sex!=null and userExtends.sex!=''">
                String user.sex=#{userExtends.sex}
            </if>
            <if test="userExtends.username!=null and userExtends.username!='' ">
                and user.username like '%${userExtends.username}%'
            </if>
        </if>
    </trim>
    </select>


// 测试用例打印的语句
Preparing: select * from user where user.sex=? and user.username like '%张三%' 

说明:prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它带来的结果就是所有在 prefixOverrides 属性中指定的内容将被移除,并且插入 prefix 属性中指定的内容。,此处是利用管道分隔符将我们的String字符进行替换成了 where字符。

set动态更新语句,set 元素可以被用于动态包含需要更新的列,而舍去其他的

<update id="updateAuthorIfNecessary">
  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语句 -->

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

foreach

foreach 元素的功能是非常强大的,它允许你指定一个集合,声明可以用在元素体内的集合项和索引变量。它也允许你指定开闭匹配的字符串以及在迭代中间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。通常是在构建 IN 条件语句的时候
你可以将任何可迭代对象(如列表、集合等)和任何的字典或者数组对象传递给foreach作为集合参数。当使用可迭代对象或者数组时,index是当前迭代的次数,item的值是本次迭代获取的元素。当使用字典(或者Map.Entry对象的集合)时,index是键,item是值。

    collection :传递参数对象中的集合属性名 
    item : 集合中存放的变量别名,用在下面的引用 
    open :开始遍历时拼接的字符串
    close :结束遍历时拼接的字符串
    separator 遍历的两个对象中需要拼接的字符串  
<select id="findUserList" parameterType="com.wf.model.UserVo" resultType="com.wf.model.UserExtends">
        select * from user
        <where>
        <include refid="usersql"></include>
        </where>
    </select>

<!--  sql语句片段引用   -->
<sql id="usersql">
        <if test="userExtends!=null">
            <if test="userExtends.sex!=null and userExtends.sex!=''">
                and user.sex=#{userExtends.sex}
            </if>
            <if test="userExtends.username!=null and userExtends.username!='' ">
                and user.username like '%${userExtends.username}%'
            </if>
        </if>
        <!--sql : select * from user where name like '%张三' and id IN(17,18,19) -->
        <if test="ids!=null"> 
            <foreach collection="ids" item="user_id" open="and id in(" close=")" separator=",">
            #{user_id}
        </foreach>
        </if>
</sql>

<!--  UserVo类  -->
public class UserVo {
    private UserExtends userExtends;

    private List<Integer> ids;   /// 设置接受多个参数的ids
}

// 测试方法 
@Test
    public void testfindUserList() {  //    测试foreach
        SqlSession session = sqlsessionfactory.openSession();
        UserDaoMapper userDaoMapper = session.getMapper(UserDaoMapper.class);
        UserVo uservo = new UserVo();
        UserExtends userExtends = new UserExtends();
        userExtends.setSex("男");
        //userExtends.setUsername("张三");
        uservo.setUserExtends(userExtends);
        List<Integer> list = new ArrayList<Integer>();  //  属性设置
        list.add(17);
        list.add(18);
        list.add(19);
        uservo.setIds(list);
        List<UserExtends> userList = userDaoMapper.findUserList(uservo);
        for(UserExtends u :userList){
            System.out.println(u.getUsername());
        }
    }

// 测试用例 打印SQL语句
Preparing: select * from user WHERE user.sex=? and id in( ? , ? , ? ) 

猜你喜欢

转载自blog.csdn.net/sinat_28978689/article/details/74897251