Mybatis中输入输出映射和动态Sql
一、输入映射
我们通过配置parameterType的值来指定输入参数的类型,这些类型可以是简单数据类型、POJO、HashMap等数据类型
1、简单类型
2、POJO包装类型
①这是单表查询的时候传入的POJO包装类型,即可以直接传入实体类,但是当多表查询的时候,就需要自定义POJO类型
②我们使用自定义POJO类型来具体的了解一下
先设计 包装类型如下,其中UserPOJO是除了User本身之外的添加的其他跟User相关的属性的包装类,UserVo是用于视图层面的包装类型,同样也是作为Mapper配置文件的输入类型
其中User文件同上一篇Mybatis简单入门中的User,包括数据表部分也一样。这里给出UserPoJO和UserVo文件
1 package cn.mybatis.po; 2 3 public class UserPoJo extends User{ 4 private User user; 5 6 public void setUser(User user) { 7 this.user = user; 8 } 9 10 public User getUser() { 11 return user; 12 } 13 }
1 package cn.mybatis.po; 2 3 public class UserVo { 4 private UserPoJo userPoJo; 5 6 public UserPoJo getUserPoJo() { 7 return userPoJo; 8 } 9 10 public void setUserPoJo(UserPoJo userPoJo) { 11 this.userPoJo = userPoJo; 12 } 13 }
然后我们配置UserMapper.xml文件
然后在UserMapper接口文件中添加
//测试包装类型的查询 public List<UserPoJo> findUserList(UserVo userVo) throws Exception;
使用Junit测试刚刚做的配置
1 @Test 2 public void testFindUserList() throws Exception { 3 SqlSession sqlSession = sqlSessionFactory.openSession(); 4 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 5 6 UserPoJo userPoJo = new UserPoJo(); 7 UserVo userVo = new UserVo(); 8 userPoJo.setSex("男"); 9 userPoJo.setUsername("u"); 10 userVo.setUserPoJo(userPoJo); 11 12 List<UserPoJo> userPoJoList = userMapper.findUserList(userVo); 13 14 System.out.println(userPoJoList); 15 }
最后结果如下
二、输出映射
1、resultType
①在使用resultType进行映射的时候,只有查询出来的列名和包装类型中的属性名一致的时候,才会映射成功
②当使用简单类型作为输出映射的时候,我们需要保证Sql查询的结果只有一行一列,这样就可以使用简单类型
如下所示示例
SELECT COUNT(*) FROM t_user SELECT username FROM t_user WHERE id = 2
2、resultMap
查询出来的列名和包装类型的属性名不一致的时候,可以使用resultMap来进行相应的映射(具体在使用中来说就是:定义resultMap中和属性的映射关系,然后将输出结果设置为resultMap的类型)
下面我们使用一个例子来进行具体的测试
①首先编写mapper配置文件,其中需要加上resultMap的配置
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="cn.mybatis.mapper.UserMapper"> 6 7 <!--定义resultMap 8 type:resultMap最终映射的Java对象类型 9 id:对resultMap的标识 10 --> 11 <resultMap id="userResultMap" type="user"> 12 <!--id:标识查询结果集中的唯一标识--> 13 <id column="_id" property="id"></id> 14 <!--result:标识查询结果集中其他列的标识--> 15 <result column="_username" property="username"></result> 16 <result column="_password" property="password"></result> 17 <result column="_sex" property="sex"></result> 18 <result column="_address" property="address"></result> 19 </resultMap> 20 21 <select id="findUserById_resultMap" parameterType="int" resultMap="userResultMap"> 22 SELECT id _id, username _username, PASSWORD _password, address _address, sex _sex FROM t_user WHERE id = #{id} 23 </select> 24 </mapper>
②然后在Mapper接口中添加方法
//测试resultMap public User findUserById_resultMap(int id) throws Exception;
③ 测试方法
1 @Test 2 public void testFindUserById_resultMap() throws Exception { 3 SqlSession sqlSession = sqlSessionFactory.openSession(); 4 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 5 6 User user = userMapper.findUserById_resultMap(2); 7 8 System.out.println(user); 9 }
④可以发现,使用resultMap的方式跟直接查询的结果是一致的
三、动态Sql
1、if判断
我们在上面使用包装类查询的用例的时候,考虑到可能出现userPoJo会是null的情况,以及其相应的属性也可能是null的情况,这样的话,如果我们直接在Sql中进行拼接而不做判断的话,可能会出现一些错误,所以我们使用if来进行动态的拼接。
<select id="findUserList" parameterType="cn.mybatis.po.UserVo" resultType="cn.mybatis.po.UserPoJo"> SELECT * FROM t_user <where> <if test="userPoJo != null"> <if test="userPoJo.sex != null and userPoJo.sex != ''"> AND sex = #{userPoJo.sex} </if> <if test="userPoJo.username != null and userPoJo.username != ''"> AND username LIKE '%${userPoJo.username}%' </if> </if> </where> </select>
2.Sql片段
上面的例子中,我们可以将if判断抽取出来作为一个Sql片段,这样做的好处是,可能再进行别的单表查询User信息的时候可以重复使用这些Sql。
1 <!--定义Sql片段--> 2 <sql id="query_user_info"> 3 <if test="userPoJo != null"> 4 <if test="userPoJo.sex != null and userPoJo.sex != ''"> 5 AND sex = #{userPoJo.sex} 6 </if> 7 <if test="userPoJo.username != null and userPoJo.username != ''"> 8 AND username LIKE '%${userPoJo.username}%' 9 </if> 10 </if> 11 </sql>
然后在别的Sql中将上面的Sql片段引入拼接即可
1 <select id="findUserList" parameterType="cn.mybatis.po.UserVo" resultType="cn.mybatis.po.UserPoJo"> 2 SELECT * FROM t_user 3 <where> 4 <include refid="query_user_info"></include> 5 </where> 6 </select>
3.foreach
当我们需要一种同样的查询方式只是参数不同的时候:SELECT * FROM t_user WHERE 1=1 AND (id = 1 OR id =2 OR id = 3),可以使用foreach来记性sql拼接
<sql id="query_ids"> <if test="ids != null"> <!-- SELECT * FROM t_user WHERE 1=1 AND (id = 1 OR id =2 OR id = 3) cilleation: 指定的是输入参数集合的属性名 item:每次遍历的名称 open:开始遍历时拼接串 close:结束遍历时候拼接的串 separator:遍历的两个对象中间需要拼接的串 --> <foreach collection="ids" item="item_id" open="AND (" close=")" separator=" OR "> id=#{item_id} </foreach> </if> </sql>
然后将上面的Sql片段加入响应的statment中
<select id="findUserByIds" parameterType="userVo" resultType="userPoJo"> SELECT * FROM t_user <where> <include refid="query_ids"></include> </where> </select>
测试结果如下