一、本课目标
- 掌握foreach的使用(重点)
- 掌握choose(when、otherwise)的使用(重点)
- 理解MyBatis的入参处理机制(难点)
二、foreach
2.1参数是数组
需求:指定用户角色(1~n个),获取这些用户角色下的用户列表信息。
分析:
1、查询SQL语句含有in条件
select * from smbms_user where userRole in (参数1,参数2,参数3...);
2、使用foreach实现
- 参数:用户角色列表
- 参数类型(数组/List)
xml配置文件:
<resultMap type="user" id="userMapByRole">
<id property="id" column="id"/>
<result property="userCode" column="userCode"/>
<result property="userName" column="userName"/>
</resultMap>
<select id="getUserByRoleId_foreach_array" resultMap="userMapByRole">
select
*
from
smbms_user
where
userRole
in
<foreach collection="array" item="roleIds"
open="(" separator="," close=")">
#{roleIds}
</foreach>
</select>
接口方法:
/**
* 根据用户角色列表,获取该角色列表下用户列表信息-foreach——array
* @param roleIds
* @return
*/
public List<User> getUserByRoleId_foreach_array(Integer[] roleIds);
测试代码:
@Test
public void testGetUserByRoleId_foreach_array() {
SqlSession sqlSession = null;
List<User> userList= new ArrayList<User>();
Integer[] roleIds = {2, 3};
try {
sqlSession = MyBatisUtil.createSqlSession();
userList = sqlSession.getMapper(UserMapper.class).getUserByRoleId_foreach_array(roleIds);
} catch (Exception e) {
e.printStackTrace();
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
for (User user:userList) {
logger.debug("mmmmmmmmmmmmmmp" + user.getUserCode() + user.getUserName());
}
}
运行结果:
注:在上面的xml文件的select标签中,并没有指定传入的参数类型,但是也能运行,这是为什么?
这是因为在配置文件中,parameterType是不用配置的,MyBatis会自动把参数封装成Map传入。但是需要注意的是,如果我们的入参是collection的话,就不能直接传入collection对象,必须要将collection转换为list或者是数组才能进行传入,否则是会报错的。
2.2参数是list
配置文件:
<select id="getUserByRoleId_foreach_list" resultMap="userMapByRole">
select
*
from
smbms_user
where
userRole
in
<foreach collection="list" item="a"
open="(" separator="," close=")">
#{a}
</foreach>
</select>
接口代码:
/**
* 根据用户角色列表,获取该角色列表下用户列表信息-foreach——list
* @param roleIds
* @return
*/
public List<User> getUserByRoleId_foreach_list(List<Integer> roleList);
测试代码:
@Test
public void testGetUserByRoleId_foreach_list() {
SqlSession sqlSession = null;
List<User> userList= new ArrayList<User>();
List<Integer> roleList = new ArrayList<Integer>();
roleList.add(2);
roleList.add(3);
try {
sqlSession = MyBatisUtil.createSqlSession();
userList = sqlSession.getMapper(UserMapper.class).getUserByRoleId_foreach_list(roleList);
} catch (Exception e) {
e.printStackTrace();
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
for (User user:userList) {
logger.debug("mmmmmmmmmmmmmmp" + user.getUserCode() + user.getUserName());
}
}
运行结果:
注:在使用foreach的时候,里面的collection属性值,如果传入的参数是数组的话,则该属性值为小写的array;如果传入的参数是集合的话,则该属性的值是小写的list。
2.3foreach的多参数入参
需求:在上一个演示示例中,增加一个参数:gender,要求查询出指定性别和用户角色列表下的用户列表。
分析:多参数入参封装Map
xml配置文件:
<select id="getUserByConditionMap_foreach_map" resultMap="userMapByRole">
select
*
from
smbms_user
where
gender=#{gender}
and
userRole
in
<foreach collection="roleIds" item="roleId"
open="(" separator="," close=")">
#{roleId}
</foreach>
</select>
接口代码:
public List<User> getUserByConditionMap_foreach_map(Map<String, Object> conditionMap);
测试代码:
@Test
public void testGetUserByConditionMap_foreach_map() {
SqlSession sqlSession = null;
List<User> userList= new ArrayList<User>();
Map<String, Object> conditionMap = new HashMap<String, Object>();
List<Integer> roleList = new ArrayList<Integer>();
roleList.add(2);
roleList.add(3);
conditionMap.put("roleIds", roleList);
conditionMap.put("gender", 1);
try {
sqlSession = MyBatisUtil.createSqlSession();
userList = sqlSession.getMapper(UserMapper.class).getUserByConditionMap_foreach_map(conditionMap);
} catch (Exception e) {
e.printStackTrace();
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
for (User user:userList) {
logger.debug("mmmmmmmmmmmmmmp" + user.getUserCode() + user.getUserName());
}
}
运行结果:
2.4单参数也可封装成Map吗?
实际上,MyBatis会把参数封装成Map进行入参,参数名是Map的key,参数值是Map的value。
xml配置文件:
<select id="getUserByRoleId_foreach_map" resultMap="userMapByRole">
select
*
from
smbms_user
where
userRole
in
<foreach collection="rKey" item="roleMap"
open="(" separator="," close=")">
#{roleMap}
</foreach>
</select>
接口代码:
public List<User> getUserByRoleId_foreach_map(Map<String, Object> roleMap);
测试代码:
@Test
public void testGetUserByRoleId_foreach_map() {
SqlSession sqlSession = null;
List<User> userList= new ArrayList<User>();
Map<String, Object> roleMap = new HashMap<String, Object>();
List<Integer> roleList = new ArrayList<Integer>();
roleList.add(2);
roleList.add(3);
roleMap.put("rKey", roleList);
try {
sqlSession = MyBatisUtil.createSqlSession();
userList = sqlSession.getMapper(UserMapper.class).getUserByRoleId_foreach_map(roleMap);
} catch (Exception e) {
e.printStackTrace();
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
for (User user:userList) {
logger.debug("mmmmmmmmmmmmmmp" + user.getUserCode() + user.getUserName());
}
}
运行结果:
三、choose(when、otherwise)
xml文件:
<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(#{creationDate})
</otherwise>
</choose>
</select>
接口方法:
public List<User> getUserList_choose(
@Param("userName")String userName,
@Param("userCode")String userCode,
@Param("userRole")Integer userRole,
@Param("creationDate")Date creationDate
);
测试代码:
@Test
public void testGetUserList_choose() {
SqlSession sqlSession = null;
List<User> userList= new ArrayList<User>();
String userName = "";
String userCode = "";
Integer userRole = 1;
try {
Date creationDate = new SimpleDateFormat("yyyy-MM-dd").parse("2016-01-01");
sqlSession = MyBatisUtil.createSqlSession();
userList = sqlSession.getMapper(UserMapper.class).getUserList_choose(userName, userCode, userRole, creationDate);
} catch (Exception e) {
e.printStackTrace();
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
for (User user:userList) {
logger.debug("mmmmmmmmmmmmmmp" + user.getUserCode() + user.getUserName());
}
}
运行结果:
注:
1、可以看到拼接出来的sql语句里面是只有一个条件的,创建日期的条件并没有拼接上去。
2、加上where 1=1这个条件的作用是避免and出错。