动态 SQL(2)
MyBatis 中 foreach 迭代
◆
◆
◆
MyBatis 入参为数组类型的 foreach 迭代
案例:根据指定角色列表来获取该角色列表下用户信息列表
/** * 根据指定角色列表来获取该角色列表下用户信息列表-foreach_array * @param roleIds 角色列表 * @return */ public List<User> getUserListByRoleIds_foreach_array(Integer[] roleIds); <!-- 根据指定角色列表来获取该角色列表下用户信息列表-foreach_array --> <select id="getUserListByRoleIds_foreach_array" resultMap="userListByRoleIds"> SELECT * FROM `smbms_user` WHERE userRole IN <foreach collection="array" item="roleIds" open="(" separator="," close=")"> #{roleIds} <!-- #{item 属性别名} --> </foreach> </select> <resultMap type="user" id="userListByRoleIds"> <id property="id" column="id" /> <result property="userCode" column="userCode" /> <result property="userName" column="userName" /> </resultMap> @Test // 测试根据指定角色列表来获取该角色列表下用户信息列表-foreach_array public void testGetUserListByRoleIds_foreach_array() { SqlSession session = null; List<User> userList = new ArrayList<User>(); Integer[] roleIds = { 2, 3 }; try { session = MyBatisUtil.getSqlSession(); userList = session.getMapper(UserMapper.class).getUserListByRoleIds_foreach_array(roleIds); } catch (Exception e) { e.printStackTrace(); } finally { MyBatisUtil.close(session); //关闭sqlSession } System.out.println("userList.size--->" + userList.size()); for (User user : userList) { System.out.println("user ====>" + "userCode:" + user.getUserCode() + ",userName:" + user.getUserName()); } }
说明:在上述示例中,我们发现 UserMapper.xml 中的 SELECT:getUserListByRoleIds_foreach_array 中并没有指定 parameterType,这样也是没有问题的。因为配置文件中的 parameterType 是可以不配置的,MyBatis 会自动把它封装成一个 Map 进行传入,但是也需要注意:若入参为 Collection 时,不能直接传入 Collection 对象,需要先将其转换为 LIST 或者数组才能传入,具体原因可参看 MyBatis 源码。
MyBatis 入参为 List 类型的 foreach 迭代
修改上面的示例,将参数类型改为传入一个 List 实例来实现同样需求。
/** * 根据指定角色列表来获取该角色列表下用户信息列表-foreach_list * @param roleIds 角色列表 * @return */ public List<User> getUserListByRoleIds_foreach_list(List<Integer> roleList); <!-- 根据指定角色列表来获取该角色列表下用户信息列表-foreach_list --> <select id="getUserListByRoleIds_foreach_list" resultMap="userListByRoleIds"> SELECT * FROM `smbms_user` WHERE userRole IN <foreach collection="list" item="roleList" open="(" separator="," close=")"> #{roleList} <!-- #{item 属性别名} --> </foreach> </select> <resultMap type="user" id="userListByRoleIds"> <id property="id" column="id"/> <result property="userCode" column="userCode"/> <result property="userName" column="userName"/> </resultMap> @Test // 测试根据指定角色列表来获取该角色列表下用户信息列表-foreach_list public void testGetUserListByRoleIds_foreach_list() { SqlSession session = null; List<User> userList = new ArrayList<User>(); List<Integer> roleList=new ArrayList<Integer>(); roleList.add(2); roleList.add(3); try { session = MyBatisUtil.getSqlSession(); userList = session.getMapper(UserMapper.class).getUserListByRoleIds_foreach_list(roleList); } catch (Exception e) { e.printStackTrace(); } finally { MyBatisUtil.close(session); //关闭sqlSession } System.out.println("userList.size--->" + userList.size()); for (User user : userList) { System.out.println("user ====>" + "userCode:" + user.getUserCode() + ",userName:" + user.getUserName()); } }
注意:foreach 元素非常强大,允许我们指定一个集合,并指定开始和结束的字符,也可加入一个分隔符到迭代器中,并能够智能处理该分膈符,不会出现多余的分隔符。
MyBatis 入参为 Map 类型的 foreach 迭代
在以上两个示例中,MyBatis 入参均为一个参数,若多个参数入参该如何处理?比如说在上一示例中需求更改为增加一个参数 gender ,要求查询出指定性别和用户角色列表下的所有用户信息列表。
除了使用 @Param 注解,若入参为多个参数,还可以把它们封装为一个 Map 进行处理。此处我们就采用这种处理方式来解决此需求。
案例:查询出指定性别和用户角色列表下的所有用户信息列表
/** * 根据用户角色列表和性别(多参数),获取该角色列表下指定性别的用户列表信息-foreach_map
* @param conditionMap 角色列表和性别封装的 map 对象 * @return */ public List<User> getUserListByConditionMap_foreach_map(Map<String, Object> conditionMap); <!--根据用户角色列表和性别(多参数),获取该角色列表下指定性别的用户列表信息-foreach_map--> <select id="getUserListByConditionMap_foreach_map" resultMap="userMapByRole"> SELECT * FROM `smbms_user` WHERE gender=#{gender} AND userRole IN <foreach collection="roleIds" item="roleMap" open="(" separator="," close=")"> #{roleMap} <!-- #{item 属性别名},collection="roleIds" Map 中相应的 key --> </foreach> </select> <resultMap type="user" id="userMapByRole"> <id property="id" column="id" /> <result property="userCode" column="userCode" /> <result property="userName" column="userName" /> </resultMap> @Test // 测试根据用户角色列表和性别(多参数),获取该角色列表下指定性别的用户列表信息-foreach_map public void testGetUserListByConditionMap_foreach_map() { SqlSession session = null; List<User> userList = new ArrayList<User>(); List<Integer> roleList=new ArrayList<Integer>(); roleList.add(2); roleList.add(3); Map<String, Object> conditionMap=new HashMap<String, Object>(); conditionMap.put("gender", 1); conditionMap.put("roleIds", roleList); try { session = MyBatisUtil.getSqlSession(); userList = session.getMapper(UserMapper.class).getUserListByConditionMap_foreach_map(conditionMap); } catch (Exception e) { e.printStackTrace(); } finally { MyBatisUtil.close(session); //关闭sqlSession } System.out.println("userList.size--->" + userList.size()); for (User user : userList) { System.out.println("user ====>" + "userCode:" + user.getUserCode() + ",userName:" + user.getUserName()); } }说明:Map 作为入参,SQL 语句中需根据 key 分别获得相应的 value 值。
如:collection="roleIds" --->conditionMap.put("roleIds", roleList) 和
gender=#{gender}--->conditionMap.put("gender", 1);
使用 Map 封装单参数入参
单参数也可以封装 Map,使用 Map 进行方法入参,我们可以自由指定 Map 的 key。实际上,MyBatis 在进行参数入参的时候,都会把它封装成一个 Map,而 Map 的 key 就是参数名,对应的参数值就是 Map 的 value。若参数为集合的时候,Map 的 key 会根据传入的是 List 还是数组对象相应地指定为 "list" 或者 "array"。
案例:修改使用数组和List 作为参数的示例,根据指定角色列表来获取用户信息列表,
使用 Map 封装单参数入参
/** * 根据用户角色列表,获取该角色列表下用户列表信息-foreach_map(单参数封装成 map) * @param roleMap 由用户角色 id 列表封装的 map 对象 * @return */ public List<User> getUserListByRoleIds_foreach_map(Map<String, Object> roleMap); <!-- 根据用户角色列表,获取该角色列表下用户列表信息-foreach_map(单参数封装成 map) --> <select id="getUserListByRoleIds_foreach_map" resultMap="userMapByRoleIds"> SELECT * FROM `smbms_user` WHERE userRole IN <foreach collection="rKey" item="roleMap" open="(" separator="," close=")"> #{roleMap} </foreach> </select> <resultMap type="user" id="userMapByRoleIds"> <id property="id" column="id" /> <result property="userCode" column="userCode" /> <result property="userName" column="userName" /> </resultMap> @Test //测试根据用户角色列表,获取该角色列表下用户列表信息-foreach_map(单参数封装成 map) public void testGetUserListByRoleIds_foreach_map() { SqlSession session = null; List<User> userList = new ArrayList<User>(); List<Integer> roleList = new ArrayList<Integer>(); roleList.add(2); roleList.add(3); Map<String, Object> roleMap=new HashMap<String, Object>(); roleMap.put("rKey", roleList); try { session = MyBatisUtil.getSqlSession(); userList = session.getMapper(UserMapper.class).getUserListByRoleIds_foreach_map(roleMap); } catch (Exception e) { e.printStackTrace(); } finally { MyBatisUtil.close(session); // 关闭sqlSession } System.out.println("userList.size--->" + userList.size()); for (User user : userList) { System.out.println("user ====>" + "userCode:" + user.getUserCode() + ",userName:" + user.getUserName()); } }
choose(when、otherwise)
讲解
案例:根据条件(用户名称、用户角色、用户编码、创建时间)查询用户表。
要求:查询条件提供前三个(用户名称、用户角色、用户编码)中的任意一个即可,
若前三个条件都不提供,那么默认提供最后一个条件(创建时间:在指定的年份内)来完成查询操作。
/** * 根据条件(用户名称、用户角色、用户编码、创建时间)查询用户表(choose用法) * @param userName 用户名称 * @param roleId 用户角色 id * @param userCode 用户编码 * @param creationDate 创建时间 * @return */ public List<User> getUserList_choose(@Param("userName")String userName, @Param("userRole")Integer roleId, @Param("userCode")String userCode, @Param("creationDate")Date creationDate); <!--根据条件(用户名称、用户角色、用户编码、创建时间)查询用户表(choose用法) --> <select id="getUserList_choose" resultType="user"> select * from smbms_user where 1=1 <choose> <when test="userName != null and userName != ''"> and userName like CONCAT ('%',#{userName},'%') </when> <when test="userCode != null and userCode != ''"> and userCode like CONCAT ('%',#{userCode},'%') </when> <when test="userRole != null"> and userRole=#{userRole} </when> <otherwise> <!-- and YEAR(creationDate) = YEAR(NOW()) --> and YEAR(creationDate) = YEAR(#{creationDate}) </otherwise> </choose> </select> @Test // 测试根据条件(用户名称、用户角色、用户编码、创建时间)查询用户表(choose用法) public void testGetUserList_choose() { SqlSession session = null; List<User> userList = new ArrayList<User>(); try { session = MyBatisUtil.getSqlSession(); String userName = ""; Integer roleId = null; String userCode = ""; Date creationDate = new SimpleDateFormat("yyyy-MM-dd").parse("2016-01-01"); userList = session.getMapper(UserMapper.class).getUserList_choose(userName, roleId, userCode, creationDate); } catch (Exception e) { e.printStackTrace(); } finally { MyBatisUtil.close(session); // 关闭sqlSession } System.out.println("userlist.size ----> " + userList.size()); for (User user : userList) { System.out.println("testGetUserList_choose=======> id: " + user.getId() + " and userCode: " + user.getUserCode() + " and userName: " + user.getUserName() + " and userRole: " + user.getUserRole() + " and creationDate: " + new SimpleDateFormat("yyyy-MM-dd").format(user.getCreationDate())); } }