14、输入映射
通过patameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型。
1、传递pojo的包装对象
完成用户信息的综合查询,需要传入查询条件(可能包括用户信息,其它信息)
建议使用自定义的包装类型的pojo
2、定义包装类型pojo
在包装类型的pojo中将复杂的查询条件包装进去
//在这里包装所需要的查询条件
//用户查询条件
private UserCustom userCustom;
public UserCustom getUserCustom() {
return userCustom;
}
public void setUserCustom(UserCustom userCustom) {
this.userCustom = userCustom;
}
3、定义映射文件mapper.xml
在userMapper.xml中定义用户信息综合查询(查询条件复杂,通过高级查询进行复杂关联查询。
<!-- 用户信息综合查询
#{userCustom.sex}:取出pojo包装对象中的性别值
-->
<select id="finduserList" parameterType="UserQueryVo"
resultType="com.fzy.mybatis.po.UserCustom">
select * from users where users.sex = #{userCustom.sex} and users.userName like '%${userCustom.userName}%'
</select>
4、mapper.java
public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception;
5、单元测试:
//用户信息的综合查询
@Test
public void testFindUserList() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//创建包装对象,设置查询条件
UserQueryVo userQueryVo = new UserQueryVo();
UserCustom userCustom = new UserCustom();
userCustom.setSex("女");
userCustom.setUserName("岩");
userQueryVo.setUserCustom(userCustom);
//调用userMapper的方法
List<UserCustom> list = userMapper.findUserList(userQueryVo);
sqlSession.close();
System.out.println(list);
}
传递hashmap
<select id=’findUserByHashmap” parameterType=”hashmap” resultType=”user”>
select * from users where userId = #{userId} and username like ‘%${userName}%’
</select>
15、输出映射
输出hashmap:
输出pojo对象可以使用hashmap输出类型,将输出的字段名称作为map的key,value为字段名。
1、resultType
输出pojo对象和pojo列表
不管是输出的pojo单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定的类型是一样的
在mapper.java指定的方法返回值类型不一样 (接口返回值类型不一样)
1、输出单个pojo对象,方法返回值是单个对象类型
2、输出pojo对象list,方法返回值是List<Pojo>
//用户信息综合查询
public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception;
//用户信息综合查询总数
public int findUserCount(UserQueryVo userQueryVo) throws Exception;
生成的动态代理对象中是根据mapper方法的返回值类型确定是调用selectOne(返回单个对象调用),还是选择selectList(返回集合对象调用)
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功
如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象
只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象
输出简单类型
用户信息的综合查询信息列表总数,通过查询总数和上边用户综合查询列表才可以实现分页
mapper.xml
<!-- 用户信息综合查询总数
parameterType:指定输入类型和findUserList一致
resultType:输出结果类型
-->
<select id="findUserList" parameterType="UserQueryVo"
resultType="int">
select count(*) from users where users.sex = #{userCustom.sex} and users.userName like '%${userCustom.userName}%'
</select>
mapper.java
//用户信息综合查询总数
public int findUserCustom(UserQueryVo userQueryVo) throws Exception;
单元测试:
//用户信息综合查询总数
@Test
public void testFindUserCount() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//创建包装对象,设置查询条件
UserQueryVo userQueryVo = new UserQueryVo();
UserCustom userCustom = new UserCustom();
userCustom.setSex("女");
userCustom.setUserName("岩");
userQueryVo.setUserCustom(userCustom);
int count = userMapper.findUserCount(userQueryVo);
System.out.println(count);
}
查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射。
2、resultMap
mybatis中可以使用resultType完成高级输出结果映射
resultMap使用方法
如果查询出来的列名和pojo的对象名不一致,通过定义一个resultMap对列名和pojo属性名之间做一个映射关系
需求:将下面的sql使用UserCustom完成映射
select userName userName_ from users where userId = #{value}
userCustom类中属性名和上边查询列名不一致
1、定义resultMap
<!-- 定义resultMap映射
select userName userName_ from users where userId = #{value}
和user类中的属性做一个映射关系
type:resultMap最终映射的java对像类型
id:对resultMap的唯一标识
-->
<resultMap type="user" id="userResultMap">
<!-- id表示查询结果集中唯一标识
column:查询出来的列名
properties:type指定的pojo类型中的属性名
最终resultMap对column和properties做一个映射关系(即对应关系)
-->
<id column="userId_" property="userId"/>
<!-- 对普通名映射定义
result:对普通名映射定义
column:查询出来的列名
properties:type指定的pojo类型中的属性名
最终resultMap对column和properties做一个映射关系(即对应关系)
-->
<result column="userName_" property="userName"/>
</resultMap>
2、使用resultMap作为statement的输出映射类型
<!-- 使用resultMap进行输出映射
resultMap:指定定义的resultMap的id,如果这个resultMap在
其他的mapper文件,前面需要加namespace
-->
<select id="findUserByIdResultMap" parameterType="int"
resultMap="userResultMap">
select userId userId_,userName userName_ from users where userId = #{value}
</select>
3、mapper.java
//根据id查询用户信息,使用resultMap输出
public User findUserByIdResultMap(int userId) throws Exception;
单元测试:
@Test
public void testFindUserByIdResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用userMapper方法
User user = userMapper.findUserByIdResultMap(4);
System.out.println(user);
}
小节:resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可映射成功
resultMap进行输出映射,
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。
16、动态sql(动态代理)
1、什么是动态 sql
mybatis核心是对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接,组装
2、需求
用户信息综合查询列表和用户信息查询列表总数这两个statement的定义使用动态sql
对查询条件进行判断,如果输入参数不为空才进行查询条件的拼接
mapper.xml
<!-- 用户信息综合查询
#{userCustom.sex}:取出pojo包装对象中的性别值
-->
<select id="findUserList" parameterType="UserQueryVo"
resultType="UserCustom">
select * from users
<!-- where可以自动去掉条件中的第一个and -->
<where>
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!=''">
and users.sex = #{userCustom.sex}
</if>
<if test="userCustom.userName!=null and userCustom.userName!=''">
and users.userName like '%${userCustom.userName}%'
</if>
</if>
</where>
</select>
<!-- 用户信息综合查询总数
parameterType:指定输入类型和findUserList一致
resultType:输出结果类型
-->
<select id="findUserCount" parameterType="UserQueryVo"
resultType="int">
select count(*) from users
<where>
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!=''">
and users.sex = #{userCustom.sex}
</if>
<if test="userCustom.userName!=null and userCustom.userName!=''">
and users.userName like '%${userCustom.userName}%'
</if>
</if>
</where>
</select>
单元测试:
//由于使用动态sql,如果不设置某个值,条件不会拼接在sql中
userCustom.setSex("女");
userCustom.setUserName("岩");
userQueryVo.setUserCustom(userCustom);
3、将上边实现的动态sql判断代码块抽取出来,组成一个sql片段,其它的statement中就可以引用sql片段
<!-- 定义sql片段
id:sql片段的唯一标识
经验:sql判断基于单表来定义sql片段,这样的sql片段重用性才高
在sql片段中不要包括where
-->
<sql id="query_user_where">
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!=''">
and users.sex = #{userCustom.sex}
</if>
<if test="userCustom.userName!=null and userCustom.userName!=''">
and users.userName like '%${userCustom.userName}%'
</if>
</if>
</sql>
引用:
<select id="findUserList" parameterType="UserQueryVo"
resultType="UserCustom">
select * from users
<!-- where可以自动去掉条件中的第一个and -->
<where>
<!-- 引用sql片段的id,如果refid指定的id不在本mapper文件中,需要前面加namespace -->
<include refid="query_user_where"></include>
<!-- 在这里还可能引用其他的sql片段:所以在sql片段中不要包含where -->
</where>
</select>
4、foreach
向sql传递数组或是List,mybatis使用foreach解析
需求:
在用户查询列表和查询总数的statement中增加多个输入查询
select * from users where userId=1 or userId=2 or userId=4
select * from users where userId in(1,2,4)
在输入参数类型中添加List<Integer>ids传入多个id
//传入多个id
private List<Integer> ids;
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
修改mapper.xml中的sql片段
<!-- foreach标签 -->
<if test="ids!=null">
<!-- 使用foreach遍历传入ids
collection:指定输入对象中的集合属性
item:每次遍历的对象名生成的对象名
open:开始遍历时拼接串
:开始是
AND (id=1 or id=2)
close:结束遍历时拼接的串
separator:遍历的两个对象中需要拼接的串
-->
<foreach collection="ids" item="user_id"
open="AND (" close=")" separator="or">
<!-- 每次遍历需要拼接的串 -->
userId=#{user_id}
</foreach>
</if>
测试:
<!-- 实现“and id IN(1,2,4)”拼接 -->
<!-- <foreach collection="ids" item="user_id"
open="and id IN(" close=")" separator=",">
#{user_id}
</foreach> -->