MyBatis之动态SQL

Posted 一宿君

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis之动态SQL相关的知识,希望对你有一定的参考价值。

学习目标

  • 列举出实现动态SQL的主要元素有哪些?
  • trim元素的主要功能是什么?
  • set元素主要用在什么操作上?
  • 有in语句查询的时候需要使用哪个元素?
  • 当List或者数组对象入参的时候,MyBatis是如何处理的?

resultType和resultMap的异同

  • resultType:表示直接返回类型

    基本数据类型
    复杂数据类型(实体类对象,集合)

  • resultMap:对外部resultMap的引用

    应用场景:

    • 数据库字段与类对象中属性字段不一致
    • 复杂的联合查询,自由控制映射结果
  • 二者不能同时存在,即使同时存在,结果是以resultMap映射为基准
  • resultMap和resultType都是Map的数据结构
  • 数据库字段信息与对象属性不一致的时候,使用resultMap自定义映射
  • 可以设置resultMap的自动映射的级别

动态SQL

  • 基于OGNL表达式
  • 完成多条件查询等逻辑实现
  • 用于实现动态SQL的元素主要有如下:
    • if
    • trim
    • where
    • set
    • choose(when、otherwise)
    • foreach

3.1 resultMap映射

  • 数据表system_userinfo:
    在这里插入图片描述
  • Java中实体类SystemUser对应数据库表system_usreinfo
    public class SystemUser implements Serializable {
        /**
         * 用户ID
         */
        private String userinfouid;
        /**
         * 登录名
         */
        private String userinfologinid;
        /**
         * 姓名
         */
        private String userinfoname;
        /**
         * 密码
         */
        private String userinfo_password;
        /**
         * 性别
         */
        private String userinfo_sex;
        /**
         * 电子邮箱
         */
        private String userinfo_email;
        /**
         * 手机
         */
        private String userinfo_mobile;
        /**
         * 用户状态(1 正常 2 锁定 3注销)
         */
        private int userinfo_status;
    
        /**
         * 用户角色id
         */
        private String userinfo_roleid;
    
        /**
         * 用户角色名
         */
        private String userinfo_rolename;
    }
    
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

if标签(判断参数) 实现简单的条件判断

  • SystemUserMapper.xml
    	<!--根据用户id和性别两个字段查询,两个字段可同时存在,也可同时为空,也可单独存在-->
    	    <select id="selectByUidOrSex" parameterType="com.ebuy.pojo.SystemUser" resultMap="userMap">
    	        select * from system_userinfo where 1 = 1
    	        <if test="userinfouid != '' and userinfouid != null">
    	            and userinfo_uid = #{userinfouid}
    	        </if>
    	        <if test="userinfo_sex != '' and userinfo_sex != null">
    	            and userinfo_sex = #{userinfo_sex}
    	        </if>
    	    </select>
    
  • SystemUserMapper接口
    /**
     * 根据用户id和性别两个字段查询,两个字段可同时存在,也可同时为空,也可单独存在
     * @param userinfouid
     * @param userinfo_sex
     * @return
     */
    SystemUser selectByUidOrSex(@Param("userinfouid")String userinfouid,@Param("userinfo_sex")String userinfo_sex);
    
  • SystemUserMapperTest
    @Test
        public void selectByUidOrSex(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class);
            SystemUser systemUser = systemUserMapper.selectByUidOrSex("1","");
            System.out.println(systemUser);
            MyBatisUtil.closeSqlSession(sqlSession);
        }
    

if+where改造SQL语句

  • SystemUserMapper.xml
    <!--用where语句改进-->
    		    <!--根据用户id和性别两个字段查询,两个字段可同时存在,也可同时为空,也可单独存在-->
    		    <select id="selectByUidOrSex2" parameterType="com.ebuy.pojo.SystemUser" resultMap="userMap">
    		        select * from system_userinfo
    		        <where>
    		            <if test="userinfouid != '' and userinfouid != null">
    		                and userinfo_uid = #{userinfouid}
    		            </if>
    		            <if test="userinfo_sex != '' and userinfo_sex != null">
    		                and userinfo_sex = #{userinfo_sex}
    		            </if>
    		        </where>
    		    </select>
    
  • SystemUserMapper接口
    /**
     * 根据用户id和性别两个字段查询,两个字段可同时存在,也可同时为空,也可单独存在
     * @param userinfouid
     * @param userinfo_sex
     * @return
     */
    SystemUser selectByUidOrSex2(@Param("userinfouid")String userinfouid,@Param("userinfo_sex")String userinfo_sex);
    
  • SystemUserMapperTest
    @Test
        public void selectByUidOrSex2(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class);
            SystemUser systemUser = systemUserMapper.selectByUidOrSex2("1","");
            System.out.println(systemUser);
            MyBatisUtil.closeSqlSession(sqlSession);
        }
    

3.5 更新用户表信息,若某个参数为null,则不需要更新,保持数据库原值(使用if+set标签)

  • SystemUserMapper.xml
    <!--更新用户信息,传入几个参数,就更新几个,判断出几个长修改参数-->
        <update id="updateUserById" parameterType="com.ebuy.pojo.SystemUser">
            update system_userinfo
            <set>
                <if test="userinfoname != '' and userinfoname != null">
                    userinfo_name = #{userinfoname},
                </if>
                <if test="userinfo_password != '' and userinfo_password != null">
                    userinfo_password = #{userinfo_password},
                </if>
                <if test="userinfo_email != '' and userinfo_email != null">
                    userinfo_email = #{userinfo_email},
                </if>
                <if test="userinfo_mobile != '' and userinfo_mobile != null">
                    userinfo_mobile = #{userinfo_mobile}
                </if>
            </set>
            where userinfo_uid = #{userinfouid}
        </update>
    
  • SystemUserMapper接口
    /**
         * 根据用户id更新用户信息
         * @param systemUser
         * @return
         */
        int updateUserById(SystemUser systemUser);
    
  • SystemUserMapperTest
    @Test
        public void updateUserById(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class);
            SystemUser systemUser = new SystemUser();
            systemUser.setUserinfouid("5");
            systemUser.setUserinfoname("王五3号");
            systemUser.setUserinfo_password("1234567");
            systemUser.setUserinfo_email("haha@163.com");
            systemUser.setUserinfo_mobile("110");
            int r = systemUserMapper.updateUserById(systemUser);
            sqlSession.commit();
            System.out.println(r);
            MyBatisUtil.closeSqlSession(sqlSession);
        }
    

trim标签的作用

  • 属性

    prefix
    suffix
    prefixOverrides
    suffixOverrides

  • 更灵活的去除关键字
  • 替代where和set

3.6 更新用户表信息,若某个参数为null,则不需要更新,保持数据库原值(使用if+trim标签替代if+set效果一样)

  • SystemUserMapper.xml
    <!--更新用户信息2,使用trim方式-->
        <update id="updateUserById2" parameterType="com.ebuy.pojo.SystemUser">
            update system_userinfo
            <trim prefix="set" prefixOverrides="," suffix="where userinfo_uid = #{userinfouid}">
                <if test="userinfoname != '' and userinfoname != null">
                    userinfo_name = #{userinfoname},
                </if>
                <if test="userinfo_password != '' and userinfo_password != null">
                    userinfo_password = #{userinfo_password},
                </if>
                <if test="userinfo_email != '' and userinfo_email != null">
                    userinfo_email = #{userinfo_email},
                </if>
                <if test="userinfo_mobile != '' and userinfo_mobile != null">
                    userinfo_mobile = #{userinfo_mobile}
                </if>
            </trim>
        </update>
    

3.7 在where条件语句不确定的情况下,判断是否拼接where语句,并且动态删除and 或者 or关键字(if+trim标签组合)

  • SystemUserMapper.xml

    <!--在where条件语句不确定的情况下使用,动态删除前面的and 或 or关键字-->
        <select id="getUserList" resultMap="userMap">
            select * from system_userinfo
            <!--prefix是前缀,prefixOverrides是要替换掉的连接关键字-->
            <trim prefix="where" prefixOverrides ="and|or">
                <if test="userinfoname != '' and userinfoname != null">
                    or userinfo_name = #{userinfoname}
                </if>
                <if test="userinfo_password != '' and userinfo_password != null">
                    and userinfo_password = #{userinfo_password}
                </if>
            </trim>
        </select>
    

    在这里插入图片描述

  • SystemUserMapper接口

    /**
     * 在where条件语句不确定的情况下使用
     * 根据用户名和密码
     * @param userifnoname
     * @param userinfo_password
     * @return
     */
    List<SystemUser> getUserList(@Param("userinfoname")String userifnoname,@Param("userinfo_password")String userinfo_password );
    
  • SystemUserMapperTest

        @Test
        public void getUserList(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class);
            List<SystemUser> systemUserList = systemUserMapper.getUserList("张三","");
            System.out.println(systemUserList);
            MyBatisUtil.closeSqlSession(sqlSession);
        }
    

foreach标签

  • 迭代一个集合,通常用于in条件
  • 属性

    item
    index
    collection:必须指定

    • list
    • array
    • map-key

    open
    separator
    close

3.8 使用foreach标签,遍历Array数组,实现SQL语句中,in关键字的作用

  • SystemUserMapper.xml
    	<!--使用foreach标签,遍历Array数组,实现SQL语句中,in关键字的作用-->
        <!--select * from system_userinfo where userinfo_roleId in (1,2,3)-->
        <select id="selectUserByArray" resultMap="userMap">
            select * from system_userinfo where userinfo_roleId in
            <foreach collection="array" item="roleIdsArray" open="(" separator="," close=")">
                #{roleIdsArray}
            </foreach>
        </select>
    
  • SystemUserMapper接口
    /**
         * 使用foreach标签,遍历Array数组,实现SQL语句中,in关键字的作用
         * @param roleIdsArray
         * @return
         */
        List<SystemUser> selectUserByArray(int[] roleIdsArray);
    
  • SystemUserMapperTest
    @Test
        public void selectUserByArray(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class);
            int[] roleIdsArray = {1,2,3};
            List<SystemUser> systemUserList = systemUserMapper.selectUserByArray(roleIdsArray);
            for(SystemUser systemUser:systemUserList){
                System.out.println(systemUser);
            }
            MyBatisUtil.closeSqlSession(sqlSession);
        }
    

3.9 使用foreach标签,遍历List集合,实现SQL语句中,in关键字的作用

  • SystemUserMapper.xml
    <!--使用foreach标签,遍历List集合,实现SQL语句中,in关键字的作用-->
        <!--select * from system_userinfo where userinfo_roleId in (1,2,3)-->
        <select id="selectUserByList" resultMap="userMap">
            select * from system_userinfo where userinfo_roleId in
            <foreach collection="list" item="roleIdsList" open="(" separator="," close=")">
                #{roleIdsList}
            </foreach>
        </select>
    
  • SystemUserMapper接口
    /**
         * 使用foreach标签,遍历List集合,实现SQL语句中,in关键字的作用
         * @param roleIdsList
         * @return
         */
        List<SystemUser> selectUserByList(List<Integer> roleIdsList);
    
  • SystemUserMapperTest
    @Test
        public void selectUserByList(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class);
            List<Integer> roleIdsList = new ArrayList<>();
            roleIdsList.add(1);
            roleIdsList.add(2);
            roleIdsList.add(3);
            List<SystemUser> systemUserList = systemUserMapper.selectUserByList(roleIdsList);
            for(SystemUser systemUser:systemUserList){
                System.out.println(systemUser);
            }
            MyBatisUtil.closeSqlSession(sqlSession);
        }
    

3.10 使用foreach标签,遍历Map集合,实现SQL语句中,in关键字的作用

  • SystemUserMapper.xml
     <!--使用foreach标签,遍历Map集合,实现SQL语句中,in关键字的作用-->
        <!--select * from system_userinfo where userinfo_roleId in (1,2,3)-->
        <select id="selectUserByMap" resultMap="userMap">
            select * from system_userinfo where userinfo_roleId in
            <foreach collection="mapRoleIdsList" item="roleIdsList" open="(" separator="," close=")">
                #{roleIdsList}
            </foreach>
        </select>
    
  • SystemUserMapper接口
    /**
         * 使用foreach标签,遍历Map集合,实现SQL语句中,in关键字的作用
         * @param roleIdsMap
         * @return
         */
        List<SystemUser> selectUserByMap(Map<String,Object> roleIdsMap);
    
  • SystemUserMapperTest
    @Test
        public void selectUserByMap(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class);
    
            /*List<Integer> roleIdsList = new ArrayList<>();
            roleIdsList.add(1);
            roleIdsList.add(2);
            roleIdsList.add(3);*/
    
            /**
             * 创建list集合也可以使用Arrays的内部方法,更为简便
             */
            List roleIdsList = Arrays.asList(1,2,3);
    
            Map<String,Object> mapRoleIdsList = new HashMap<>();
            mapRoleIdsList.put("mapRoleIdsList", roleIdsList);
    
            List<SystemUser> systemUserList = systemUserMapper.selectUserByMap(mapRoleIdsList);
            for(SystemUser systemUser:systemUserList){
                System.out.println(systemUser);
            }
            MyBatisUtil.closeSqlSession(sqlSession);
        }
    

choose(when、otherwise)

  • 相当于Java中switch语句
  • 当when有条件满足时,就跳出choose,不再执行后面的when和otherwise

3. 11 使用choose与when方式,与if标签不同之处在于,当其中一个when条件满足后,就不在执行后面的when语句

  • SystemUserMapper.xml
    <!--使用choose与when方式-->
        <!--if标签不同之处在于,当其中一个when条件满足后,就不在执行后面的when语句-->
        <select id="selectUserByChoose" resultMap="userMap">
            select * from system_userinfo where 1=1
            <choose>
                <when test="userinfoname!=null and userinfoname!=''">
                    and userinfo_name like concat(concat('%',#{userinfoname}),'%')
                </when>
                <when test="userinfo_sex !=null and userinfo_sex!=''">
                    and userinfo_sex=#{userinfo_sex}
                </when>
                <otherwise>
                    and 2=2
                </otherwise>
            </choose> 
        </select>
    
  • SystemUserMapper接口
    /**
     *
     * @param userinfoname
     * @param userinfo_sex
     * @return
     */
    List<SystemUser> selectUserByChoose(@Param("userinfoname")String userinfoname,@Param("userinfo_sex")String userinfo_sex);
    
  • SystemUserMapperTest
    @Test
        public void selectUserByChoose(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class);
    
            List<SystemUser> systemUserList = systemUserMapper.selectUserByChoose("","");
            for(SystemUser systemUser:systemUserList){
                System.out.println(systemUser);
            }
            MyBatisUtil.closeSqlSession(sqlSession);
        }
    

3.12 分页查询