Mybatis框架的使用之五(动态SQL)

在这里插入图片描述

假定一张用户表,要通过姓名(userName)模糊以及职位id(userRole)筛选显示所有符合条件的信息。普通sql语句的写法是:

select * from user 
where userName CONCAT('%',#{userName},'%') 
and userRole ={userRole}

有这样一种情况,在用户进行多条件查询数据或更新数据的时候,可能会不进行一项或多项参数的传值,比如userName不进行传参,那么执行的时候上述语句实际执行的是
select * from user where userName CONCAT(’%’,null,’%’) and userRole ={userRole}
模糊查询名字中有null,职位id是xx的人,这样很显然查不出数据,达不到预期的设想。

解决方案:if+trim标签
上述语句可以优化为:

//省略代码
 select * from user
        <trim prefix="where" prefixOverrides="and">
            <if test="userName!=null and userName !=''">
                AND userName like CONCAT('%',#{userName},'%')
            </if>
            <if test="userRole!=null">
                AND userRole = #{userRole}
            </if>
       </trim>
 //省略代码

这条语句的意思就是:如果userName不为null且不为空字符串,就执行这一部分语句,并在语句之前增加 ‘where’ 关键字,否则跳过。如果userRole不为null,就进行这一部分语句,并在语句之前增加 ‘where’ 关键字(如果之前的语句已经增加过了就不会再增加)。如果有上述内容中有多余的’and’关键字,就把它删除。

首先< if>< /if>标签的作用与在Java中一样,是进行一个判断,"test"属性就是要判断的条件,如果返回值为真,则进行标签内语句,否则跳过。
< trim>< /trim>标签则是对多余的sql语句进行动态的修改,prefix表示开头的信息,如果后面的if条件有返回值就会在开头加上,prefixOverrides表示结尾指定内容的忽略 suffix表示最后的固定结尾内容,在这条语句中没有使用到。

通过这样的修改,假设当传入的userName是null或者’’,userRole是1的时候,语句会动态的修改成
select * from user
where userRole =1

或者当传入的userName是"赵"而userRole是null的时候,语句会动态的修改成:
select * from user
where userRole =1
where userName like CONCAT(’%’,‘赵’,’%’)

又或者,当userName和userRole都是null,那么语句会动态的修改成:
select * from user

总的来说< trim>标签很强大,除了select ,update set也可以使用,就不赘述了。

< foreach>标签
需求:指定用户职位userRole(1-n个),获取这些用户角色下的用户列表信息
举例:select * from user where userRole in (2,3)

		//省略代码
        select * from user where userRole in
        <foreach collection="array" 
        item="roleIds" open="(" separator="," close=")">
            #{roleIds}
        </foreach>
        //省略代码

属性:
item:集合里每一个元素进行迭代时的别名
index:指定一个名称,代表每次迭代到的位置
collection:必须指定 。list、array、map-key
open:表示语句以什么来开始
separator:迭代之间以什么符号进行间隔
close:语句以什么结束

上述mapper方法对应的接口方法是

List<User> getUserByRoleId_foreach_array(Integer[] roleIds);

测试方法:

public void getUserByRoleId_foreach_array() {
        SqlSession sqlSession = null;
        List<User> userList = new ArrayList<>();
        Integer[] roleIds = {1, 2};
        try {
            sqlSession = MyBatisUtils.getSQLSession();
            userList = sqlSession.getMapper(UserMapper.class).getUserByRoleId_foreach_array(roleIds);
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
        for (User user : userList) {
            logger.debug("user ===========> id: " + user.getId() +
                    ", userName: " + user.getUserName() +
                    ", userAddress: " + user.getAddress() +
                    ", userRole: " + user.getUserRole());
        }
    }

上述代码中指定了迭代的类型(collection)是数组array,实际上迭代集合list也是基本一致的用法。

collection:map-key 这里迭代的是一个map,具体到map的key。

需求:指定用户职位userRole(1-n个),且性别(gender)是1的用户,获取这些用户列表信息

从需求可以看出实际上有两个限制条件,条件1是固定值,条件2是个集合。这样就可以考虑用map的方式进行迭代查询。

接口方法:

List<User> getUserByRoleId_foreach_map(Map<String,Object> roleMap);

mapper文件:

//省略代码
  select * from user where gender=#{gender} 
        AND userRole IN
        <foreach collection="userRole" item="roleMap" 
        open="(" separator="," close=")">
            #{roleMap}
        </foreach>
//省略代码

测试方法:

 public void getUserByRoleId_foreach_map() {
        SqlSession sqlSession = null;
        Map<String,Object> roleMap = new HashMap<>();
        List<Integer> roleList = new ArrayList<>();
        roleList.add(2);
        roleList.add(3);
        roleMap.put("gender",1);
        roleMap.put("userRole",roleList);
        List<User> userList = new ArrayList<>();
        try {
            sqlSession = MyBatisUtils.getSQLSession();
            userList = sqlSession.getMapper(UserMapper.class).getUserByRoleId_foreach_map(roleMap);
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
        logger.debug("getUserListByRoleIdTest userList.size : " + userList.size());
        for (User user : userList) {
            logger.debug("user ===========> id: " + user.getId() +
                    ", userName: " + user.getUserName() +
                    ", userAddress: " + user.getAddress() +
                    ", userRole: " + user.getUserRole()+
                    ", gender: " + user.getGender()
            );
        }
    }

这里值得注意的就是用于存放userRole参数的list集合的key名要跟mapper映射文件里的collection的值保持一致。用于存放所有参数的map集合的key要跟mapper映射文件里的item的值以及#{参数名}保持一致。

到这里,Mybatis的使用系列就告一段落,该吃午饭了。

猜你喜欢

转载自blog.csdn.net/wangduanqs/article/details/85063368
今日推荐