(三)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 分页查询

  • SystemUserMapper.xml
    <!--分页查询-->
        <!--
          start是起始记录数
          end是结尾记录数
          &lt; 代表小于号
          &gt; 代表大于号
        -->
        <select id="selectUserByStartAndEnd" resultMap="userMap">
            select * from (
            select t.*,rownum r from (
            select * from system_userinfo order by to_number(userinfo_uid) desc
            ) t where rownum &lt;= #{end}
            ) where r &gt; #{start}
        </select>
    
  • SystemUserMapper接口
    /**
     * 分页查询
     * @param start
     * @param end
     * @return
     */
    List<SystemUser> selectUserByStartAndEnd(@Param("start")int start,@Param("end")int end);
    
  • SystemUserMapperTest
    @Test
        public void selectUserByStartAndEnd(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class);
            int pageSize = 2;
            int currentPage = 1;
            int start = (currentPage-1)*pageSize;
            int end = currentPage*pageSize;
            List<SystemUser> systemUserList = systemUserMapper.selectUserByStartAndEnd(start,end);
            for(SystemUser systemUser:systemUserList){
                System.out.println(systemUser);
            }
            MyBatisUtil.closeSqlSession(sqlSession);
        }
    

3. 13 select小结

在这里插入图片描述

3.14 insert

  • id(对应DaoMapper映射接口中的方法名)
  • parameterType(参数类型,int、String、Date、类对象)
        <!--插入角色数据-->
        <insert id="save" parameterType="SystemRole">
            insert into system_role(role_id,role_name,role_code,role_description)
            values(SEQ_SYSTEM_ROLE_ID.nextval,#{role_name},#{role_code},#{role_description})
        </insert>
    
  • DaoMapper接口
    /**
         * 插入角色数据
         * @param SystemRole
         * @return
         */
        int save(SystemRole SystemRole);
    
  • SystemRoleMapperTest
    @Test
        public void save(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemRoleMapper systemRoleMapper = sqlSession.getMapper(SystemRoleMapper.class);
            SystemRole systemRole = new SystemRole();
            systemRole.setRole_name("财务管理员");
            systemRole.setRole_code("cwadmin");
            systemRole.setRole_description("管理所有财务业务");
    
            int r = systemRoleMapper.save(systemRole);
    
            /**
             * 非常关键的一步是,更新或插入数据,执行SQL后要手动进行提交
             */
            sqlSession.commit();
            System.out.println("成功插入:" + r + "条角色数据");
        }
    

3.15 update

  • id(对应DaoMapper映射接口中的方法名)
  • parameterType(参数类型,int、String、Date、类对象)
       <!--根据roleId更新角色信息-->
        <update id="updateByRoleId" parameterType="SystemRole">
            update system_role set role_name=#{role_name},role_code=#{role_code},
               role_description=#{role_description} where role_id=#{role_id}
        </update>
    
  • DaoMapper接口
    /**
         * 根据roleId更新信息
         * @param systemRole
         * @return
         */
        int updateByRoleId(SystemRole systemRole);
    
  • SystemRoleMapperTest
    @Test
        public void updateByRoleId(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemRoleMapper systemRoleMapper = sqlSession.getMapper(SystemRoleMapper.class);
            SystemRole systemRole = new SystemRole();
            systemRole.setRole_id("7");
            systemRole.setRole_name("财务管理员222222");
            systemRole.setRole_code("cwadmin22222");
            systemRole.setRole_description("管理所有财务业务22222");
    
            int r = systemRoleMapper.updateByRoleId(systemRole);
    
            /**
             * 非常关键的一步是,更新或插入数据,执行SQL后要手动进行提交
             */
            sqlSession.commit();
            System.out.println("成功更新:" + r + "条角色数据");
        }
    

3.16 update(使用trim方式)

  • 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>
    
  • SystemUserMapper接口
    /**
         * 根据用户id更新用户信息2,使用trim方式
         * @param systemUser
         * @return
         */
        int updateUserById2(SystemUser systemUser);
    
  • SystemUserMapperTest
    @Test
        public void updateUserById2(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class);
            SystemUser systemUser = new SystemUser();
            systemUser.setUserinfouid("5");
            systemUser.setUserinfoname("王五55555号");
            systemUser.setUserinfo_password("1234567");
            systemUser.setUserinfo_email("haha@163.com");
            systemUser.setUserinfo_mobile("110");
            int r = systemUserMapper.updateUserById2(systemUser);
            sqlSession.commit();
            System.out.println(r);
            MyBatisUtil.closeSqlSession(sqlSession);
        }
    

3.17 delete

  • id(对应DaoMapper映射接口中的方法名)
  • parameterType(参数类型,int、String、Date、类对象)
        <!--根据roleId删除角色信息-->
        <delete id="deleteByRoleId" parameterType="String">
            delete from system_role where role_id=#{role_id}
        </delete>
    
  • DaoMappere接口
    /**
         * 根据roleId删除信息
         * @param systemRole
         * @return
         */
        int deleteByRoleId(SystemRole systemRole);
    
  • SystemRoleMapperTest
    @Test
        public void deleteByRoleId(){
            SqlSession sqlSession = MyBatisUtil.createSqlSession();
            SystemRoleMapper systemRoleMapper = sqlSession.getMapper(SystemRoleMapper.class);
            SystemRole systemRole = new SystemRole();
            systemRole.setRole_id("7");
    
            int r = systemRoleMapper.deleteByRoleId(systemRole);
    
            /**
             * 非常关键的一步是,更新或插入数据,执行SQL后要手动进行提交
             */
            sqlSession.commit();
            System.out.println("成功删除:" + r + "条角色数据");
        }
    

    注意:insert、update、delete元素均没有resultType属性

动态sql总结在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一宿君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值