zoukankan      html  css  js  c++  java
  • Java -- MyBatis学习笔记9、动态SQL

    1、内容列表

    • 动态SQL-if
    • 动态SQL-where
    • 动态SQL-foreach
    • 动态SQL-片段

    动态SQL,通过MyBatis提供的各种标签对条件作出判断以实现动态拼接SQL语句。这里的条件判断使用的表达式为OGNL表达式。常用的动态SQL标签有等。MyBatis的动态SQL语句,与 JSTL中的语句非常相似。动态SQL主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行查询。提交的查询条件不同,执行的SQL语句不同。若将每种可能的情况均逐一列出,对所有条件进行排列组合,将会出现大量的SQL语句。此时,可使用动态 SQL 来解决这样的问题.

    在 mapper 的动态 SQL 中若出现大于号(>)、小于号(<)、大于等于号(>=),小于等于号(<=)等符号,最好将其转换为实体符号。否则,XML 可能会出现解析出错问题。特别是对于小于号(<),在 XML 中是绝不能出现的。否则解析 mapper 文件会出错。

    • 实体符号表:
    原始符号 实体符号
    < <
    > >
    >= >=
    <= <=

    1.1、动态SQL之<if>

    对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中。

    • 语法:<if test=”条件”> sql语句的部分
    • 接口方法:
    List<UserInfo> selectUserAll(UserInfo userInfo);
    

    mapper文件:

    <select id="selectUserAll" resultType="com.rg.entity.UserInfo">
        select * from UserInfo where 1 = 1
            <if test="name != null and name != '' ">
                    and name = #{Name}
            </if>
            <if test="age > 0">
                and age < #{Age}
            </if>
    </select>
    
    • 测试方法:
    @Test
        public void test01()
        {
            UserInfo userInfo = new UserInfo();
            userInfo.setName("王五");
            userInfo.setAge(15);
            List<UserInfo> userList = this.userInfoDao.selectUserAll(userInfo);
            System.out.println(userList);
        }
    

    1.2、动态SQL之<where>

    if标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若where后的所有if条件均为false,而where后若又没有 1=1 子句,则SQL中就会只剩下一个空的where,SQL出错。所以,在where后,需要添加永为真子句 1=1,以防止这种情况的发生。但当数据量很大时,会严重影响查询效率。

    使用标签,在有查询条件时,可以自动添加上where 子句;没有查询条件时,不会添加where子句。需要注意的是,第一个if标签中的SQL片断,可以不包含and。不过,写上and也不错,系统会将多出的and去掉。但其它if中SQL片断的and,必须要求写上。否则SQL语句将拼接出错。

    • 语法:<where> 其他动态 sql </where>
    • 接口方法:
    List<UserInfo> selectUserAll(UserInfo userInfo);
    

    mapper文件:

    <select id="selectUserAll" resultType="com.rg.entity.UserInfo">
         select * from UserInfo
            <where>
                <if test="name != null and name != '' ">
                    and name = #{Name}
                </if>
                <if test="age > 0">
                    and age < #{Age}
                </if>
            </where>
    </select>
    
    • 测试方法:
    @Test
        public void test01()
        {
            UserInfo userInfo = new UserInfo();
            userInfo.setName("王五");
            userInfo.setAge(15);
            List<UserInfo> userList = this.userInfoDao.selectUserAll(userInfo);
            System.out.println(userList);
        }
    

    1.3、动态SQL之<foreach>

    <foreach/>标签用于实现对于数组与集合的遍历。对其使用,需要注意:

    • collection 表示要遍历的集合类型, list ,array 等。
    • open:循环开始时的字符
    • close:循环结束时的字符
    • separator 为对遍历内容的SQL拼接。也就是中间的分隔符
    • item:自定义的、表示数组或者集合中成员的变量、就像:
    for(Object obj : UserList)
    {
         //item就是括号里边的obj
    }
    

    1.4、语法:

    <foreach collection="集合类型" open="开始的字符" close="结束的字符"item="集合中的成员" separator="集合成员之间的分隔符">
    	#{item 的值}
    </foreach>
    

    1.5、遍历List<简单类型>

    • 接口方法:
    List<UserInfo> selectUserForList(List<Integer> list);
    
    • mapper文件:
    <select id="selectUserForList" resultType="com.rg.entity.UserInfo">
         select * from UserInfo
            <if test="list != null and list.size > 0">
                where id in
                <foreach collection="list" open="(" close=")" separator="," item="id">
                    #{id}
                </foreach>
            </if>
    </select>
    
    • 测试方法:
    @Test
        public void test02()
        {
            List<Integer> list = new ArrayList<>();
            list.add(3);
            list.add(5);
            list.add(7);
            List<UserInfo> userInfoList = this.userInfoDao.selectUserForList(list);
            System.out.println(userInfoList);
        }
    

    1.6、遍历List<对象类型>

    • 接口方法:
    List<UserInfo> selectUserForListObj(List<UserInfo> userList);
    
    • mapper文件:
    <select id="selectUserForListObj" resultType="com.rg.entity.UserInfo">
         select * from UserInfo
            <if test="list != null and list.size > 0">
                where id in
                <foreach collection="list" open="(" close=")" separator="," item="userObj">
                    #{userObj.id}
                </foreach>
            </if>
    </select>
    
    • 测试方法:
    @Test
        public void test03()
        {
            //声明集合、里边存放UserInfo对象
            List<UserInfo> userList = new ArrayList<>();
            UserInfo userInfo = new UserInfo();
            userInfo.setId(3);
            //添加到集合当中
            userList.add(userInfo);
            //再实例化一个对象
            userInfo = new UserInfo();
            userInfo.setId(5);
            userList.add(userInfo);
            List<UserInfo> userInfoList = this.userInfoDao.selectUserForListObj(userList);
            System.out.println(userInfoList);
        }
    

    1.7、动态SQL之代码片段

    标签用于定义SQL片断,以便其它SQL标签复用。而其它标签使用该SQL片断,需要使用<include/>子标签。该标签可以定义 SQL 语句中的任何部分,所以<include/>子标签可以放在动态 SQL的任何位置。

    • 接口方法:
    List<UserInfo> selectUserForListObj(List<UserInfo> userList);
    
    • mapper文件:
    <sql id="selectUser">
            select * from UserInfo
    </sql>
    <select id="selectUserForListObj" resultType="com.rg.entity.UserInfo">
        <include refid="selectUser"/>
            <if test="list != null and list.size > 0">
                where id in
                <foreach collection="list" open="(" close=")" separator="," item="userObj">
                    #{userObj.id}
                </foreach>
            </if>
    </select>
    
    • 测试方法:
    @Test
        public void test03()
        {
            //声明集合、里边存放UserInfo对象
            List<UserInfo> userList = new ArrayList<>();
            UserInfo userInfo = new UserInfo();
            userInfo.setId(3);
            //添加到集合当中
            userList.add(userInfo);
            //再实例化一个对象
            userInfo = new UserInfo();
            userInfo.setId(5);
            userList.add(userInfo);
            List<UserInfo> userInfoList = this.userInfoDao.selectUserForListObj(userList);
            System.out.println(userInfoList);
        }
    

    <sql/>标签很好理解、就是将能够复用的SQL语句封装起来、设置一个标识符、在<include/>里边通过标识符找到对应的SQL标签、另外、看到<include/>里边查找对应的SQL标签用的是refid、就知道里边采用的是反射机制。

  • 相关阅读:
    HYSBZ 3813 奇数国
    HYSBZ 4419 发微博
    HYSBZ 1079 着色方案
    HYSBZ 3506 排序机械臂
    HYSBZ 3224 Tyvj 1728 普通平衡树
    Unity 3D,地形属性
    nginx 的naginx 种包含include关键字
    Redis 出现NOAUTH Authentication required解决方案
    mysql 8.0出现 Public Key Retrieval is not allowed
    修改jar包里的源码时候需要注意的问题
  • 原文地址:https://www.cnblogs.com/dcy521/p/14748627.html
Copyright © 2011-2022 走看看