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{ 4private User user; 5 6public void setUser(User user) { 7this.user = user; 8} 9 10public User getUser() { 11return user; 12} 13 } UserPOJO
1 package cn.mybatis.po; 2 3 public class UserVo { 4private UserPoJo userPoJo; 5 6public UserPoJo getUserPoJo() { 7return userPoJo; 8} 9 10public void setUserPoJo(UserPoJo userPoJo) { 11this.userPoJo = userPoJo; 12} 13 } UserVo
然後我們配置UserMapper.xml檔案
然後在UserMapper介面檔案中新增
//測試包裝型別的查詢 public List<UserPoJo> findUserList(UserVo userVo) throws Exception;
使用Junit測試剛剛做的配置
1@Test 2public void testFindUserList() throws Exception { 3SqlSession sqlSession = sqlSessionFactory.openSession(); 4UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 5 6UserPoJo userPoJo = new UserPoJo(); 7UserVo userVo = new UserVo(); 8userPoJo.setSex("男"); 9userPoJo.setUsername("u"); 10userVo.setUserPoJo(userPoJo); 11 12List<UserPoJo> userPoJoList = userMapper.findUserList(userVo); 13 14System.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 3PUBLIC "-//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 8type:resultMap最終對映的Java物件型別 9id:對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"> 22SELECT 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 2public void testFindUserById_resultMap() throws Exception { 3SqlSession sqlSession = sqlSessionFactory.openSession(); 4UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 5 6User user = userMapper.findUserById_resultMap(2); 7 8System.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 != ''"> 5AND sex = #{userPoJo.sex} 6</if> 7<if test="userPoJo.username != null and userPoJo.username != ''"> 8AND 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"> 2SELECT * 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>
測試結果如下