Spring+SpringMVC+MyBatis深入學習及搭建(四)——MyBatis輸入映射與輸出映射
轉載請註明出處:http://www.cnblogs.com/Joanna-Yan/p/6878529.html
前面有講到Spring+SpringMVC+MyBatis深入學習及搭建(三)——MyBatis全局配置文件解析
1. 輸入映射
通過parameterType指定輸入參數的類型,類型可以是簡單類型、hashmap、pojo的包裝類型。
1.1 #{}與${}
#{}實現的是向prepareStatement中的預處理語句設置參數值,sql語句中#{}表示一個占位符即?
<select id="findUserById" parameterType="int" resultType="user"> select * from user where id=#{id} </select>
使用占位符#{}可以有效防止sql註入,在使用時不需要關系參數值的類型,mybatis會自動進行java類型和jdbc類型的轉換。#{}可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個類型值,#{}括號可以是value或其它名稱。
${}和#{}不同,通過${}可以將parameterType傳入的內容拼接在sql中且不進行jdbc類型轉換,${}可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,${}括號中只能是value。使用${}不能防止sql註入,但是有時用${}會非常方便,如下例子:
<select id="findUserByName" parameterType="java.lang.String" resultType="joanna.yan.mybatis.entity.User"> select * from user where username LIKE ‘%${value}%‘ </select>
如果本例子使用#{}則傳入的字符串中必須要有%,而%是人為拼接在參數中,顯然有點麻煩,如果采用${}在sql中拼接為%的方式則在調用mapper接口傳遞參數就方便很多。
//如果使用占位符號則必須人為在傳參數中加%List<User> list = userMapper.selectUserByName("%管理員%");
//如果使用${}原始符號則不用人為在參數中加% List<User>list = userMapper.selectUserByName("管理員");
再比如order by排序,如果將列名通過參數傳入sql,根據傳的列名進行排序,應該寫為:ORDER BY ${columnName}
如果使用#{}將無法實現此功能。
1.2 傳遞簡單類型
參考上邊的例子。
1.3 傳遞pojo對象
mybatis使用ognl表達式解析對象字段的值,如下例子:
<!--傳遞pojo對象綜合查詢用戶信息 --> <select id="findUserByUser" parameterType="user" resultType="user"> select * from user where id=#{id} and username like ‘%${username}%‘ </select>
sql中紅色標註的是user對象中的字段名稱。
測試:
@Test public void findUserByUserTest() throws Exception{ SqlSession sqlSession=sqlSessionFactory.openSession(); UserMapper userMapper=sqlSession.getMapper(UserMapper.class); User user=new User(); user.setId(10); user.setUsername("張三"); List<User> list=userMapper.findUserByUser(user); System.out.println(list); sqlSession.close(); }
1.4 傳遞pojo包裝對象
開發中通過pojo傳遞查詢條件,查詢條件是綜合的查詢條件,不僅包括用戶查詢條件,還包括其它的查詢條件(比如將用戶購買的商品信息也作為查詢條件),這時可以使用包裝對象傳遞輸入參數。
1.4.1 需求
完成用戶信息的綜合查詢,需要傳入查詢條件很復雜(可能包括用戶信息、其它信息,比如商品、訂單等)
1.4.2 定義包裝類型pojo
針對上邊需求,建議使用自定義的包裝類型的pojo,在包裝類型的pojo中將復雜的查詢條件包裝進去。
/** * 包裝類型 * @author Joanna.Yan * */ public class UserQueryVo { //在這裏包裝所需要的查詢條件 //用戶查詢條件 private UserCustom userCustom; public UserCustom getUserCustom() { return userCustom; } public void setUserCustom(UserCustom userCustom) { this.userCustom = userCustom; } //可以包裝其它的查詢條件,訂單、商品 //...... }
1.4.3 mapper.xml
在UserMapper.xml中定義用戶信息綜合查詢(查詢條件復雜,通過高級查詢進行復雜關聯查詢)
<!--用戶信息綜合查詢 UserQueryVo中定義了userCustom屬性 #{userCustom.sex}:取出pojo包裝對象中性別值 ${userCustom.username}:取出pojo包裝對象中用戶名稱 --> <select id="findUserList" parameterType="joanna.yan.mybatis.entity.UserQueryVo" resultType="joanna.yan.mybatis.entity.UserCustom"> SELECT * FROM USER WHERE user.sex=#{userCustom.sex} AND user.username LIKE ‘%${userCustom.username}%‘ </select>
1.4.4 mapper.java
//用戶信息綜合查詢 public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception;
1.4.5 測試代碼
@Test public void findUserListTest() throws Exception{ SqlSession sqlSession=sqlSessionFactory.openSession(); UserMapper userMapper=sqlSession.getMapper(UserMapper.class); //創建包裝對象,設置查詢條件 UserQueryVo userQueryVo=new UserQueryVo(); UserCustom userCustom=new UserCustom(); userCustom.setSex("1"); userCustom.setUsername("張三豐"); userQueryVo.setUserCustom(userCustom); List<UserCustom> list=userMapper.findUserList(userQueryVo); System.out.println(list); }
1.5 傳遞hashmap
sql映射文件定義如下:
<!--傳遞hashmap綜合查詢用戶信息 --> <select id="findUserByHashmap" parameterType="hashmap" resultType="user"> select * from user where id=#{id} and username like ‘%${username}%‘ </select>
sql中紅的標註的是hashmap的key。
mapper.java:
//傳遞hashmap綜合查詢用戶信息
public List<User> findUserByHashmap(HashMap<String, Object> map) throws Exception;
測試:
@Test public void findUserByHashmapTest() throws Exception{ SqlSession sqlSession=sqlSessionFactory.openSession(); UserMapper userMapper=sqlSession.getMapper(UserMapper.class); //構造查詢條件HashMap對象 HashMap<String, Object> map=new HashMap<>(); map.put("id", 10); map.put("username", "張三"); //傳遞HashMap對象查詢用戶列表 List<User> list=userMapper.findUserByHashmap(map); System.out.println(list); sqlSession.close(); }
傳遞的map中的key和sql中解析的key不一致時,不會報錯,只是通過key獲取的值為空。
2. 輸出映射
2.1 輸出簡單類型
看下邊的例子,輸出整型,mapper.xml文件:
<!--獲取用戶列表總數 --> <select id="findUserCount" parameterType="user" resultType="int"> select count(*) from user </select>
mapper接口:
public interface UserMapper { //獲取用戶列表總數 public int findUserCount(User user) throws Exception; }
測試:
[email protected] public void findUserCountTest() throws Exception{ SqlSession sqlSession=sqlSessionFactory.openSession(); //創建UserMapper對象,mybatis自動生成mapper代理對象 UserMapper userMapper=sqlSession.getMapper(UserMapper.class); User user=new User(); user.setUsername("yan"); //調用userMapper的方法 int count=userMapper.findUserCount(user); System.out.println(count); sqlSession.close(); }
總結:
查詢出來的結果集只有一行且一列,可以使用簡單類型進行輸出映射。
2.2 輸出pojo對象和pojo列表
不管是輸出的pojo單個對象還是一個列表(list中包括pojo),在mapper.xml中resultType指定的類型是一樣的。
在mapper.java指定的方法返回值類型不一樣:
(1)輸出單個pojo對象,方法返回值是單個對象類型。
(2)輸出pojo對象list,方法返回值是List<POJO>
生成的動態代理對象中是根據mapper方法的返回值類型確定是調用session.selectOne(返回單個對象調用)還是session.selectList(返回集合對象調用)。
2.3 resultType總結
使用resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才可以映射成功。
如果查詢出來的列名和pojo中的屬性名全部不一致,則不會創建pojo對象。
只要查詢出來的列名和pojo中的屬性有一個一致,就會創建pojo對象。
2.4 輸出hashmap
輸出pojo對象可以改用hashmap輸出類型,將輸出的字段名稱作為map的key,value為字段值。
2.5 resultMap
resultType可以指定將查詢結果映射為pojo,但需要pojo的屬性名和sql查詢的列名一致才可映射成功。
如果sql查詢字段名和pojo的屬性名不一致,可以通過resultMap將字段名和屬性名作一個對應關系,resultMap實質上還需要將查詢結果映射到pojo對象中。
resultMap可以實現將查詢結果映射為復雜類型的pojo,比如在查詢結果映射對象中包括pojo和list實現實現一對一查詢和一對多查詢。
2.5.1 resultMap使用方法
如果查詢出來的列名和pojo的屬性名不一致,通過定義一個resultMap對列名和pojo屬性名之間作一個映射關系。
(1)定義resultMap
(2)使用resultMap作為statement的輸出映射類型。
2.5.2 將下邊的sql使用User完成映射
SELECT id id_,username username_ FROM USER WHERE id=#{value}
改sql對查詢結果的列名進行了重新命名:
User類中屬性名和上邊查詢列名不一致。
2.5.2.1 定義resultMap
<!--定義resultMap 將SELECT id id_,username username_ FROM USER和User類中的屬性作一個映射關系。 type:resultMap最終映射的java對象類型,可以使用別名 id:對resultMap的唯一標識 --> <resultMap type="user" id="userResultMap"> <!--id表示查詢結果集中唯一標識 column:查詢出來的列名 property:type指定的pojo類型中的屬性名 最終resultMap對column和property作一個映射關系(對應關系) --> <id column="id_" property="id"/> <!--result:對普通名映射定義 column:查詢出來的列名 property:type指定的pojo類型中的屬性名 最終resultMap對column和property作一個映射關系(對應關系) --> <result column="username_" property="username"/> </resultMap>
2.5.2.2 使用resultMap作為statement的輸出映射類型
<!--使用resultMap進行輸出映射 resultMap:指定定義的resultMap的id,如果這個resultMap在其它的mapper文件,前邊需要加namespace --> <select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap"> SELECT id id_,username username_ FROM USER WHERE id=#{value} </select>
2.5.2.3 mapper.java
//根據id查詢用戶信息,使用resultMap輸出 public User findUserByIdResultMap(int id) throws Exception;
2.5.2.4 測試
@Test public void findUserByIdResultMapTest() throws Exception{ SqlSession sqlSession=sqlSessionFactory.openSession(); UserMapper userMapper=sqlSession.getMapper(UserMapper.class); User user=userMapper.findUserByIdResultMap(1); System.out.println(user); sqlSession.close(); }
2.6 小結
使用resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才可以映射成功。
如果查詢出來的列名和pojo的屬性名不一致,通過定義一個resultMap對列名和pojo屬性名之間作一個映射關系。
如果此文對您有幫助,微信打賞我一下吧~
Spring+SpringMVC+MyBatis深入學習及搭建(四)——MyBatis輸入映射與輸出映射