1. 程式人生 > >Spring+SpringMVC+MyBatis深入學習及搭建(四)——MyBatis輸入映射與輸出映射

Spring+SpringMVC+MyBatis深入學習及搭建(四)——MyBatis輸入映射與輸出映射

指定 2.6 face 生成 shm hashmap ace and 包裝

轉載請註明出處: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輸入映射與輸出映射