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

来源:http://www.cnblogs.com/Joanna-Yan/archive/2017/05/26/6878529.html
-Advertisement-
Play Games

轉載請註明出處:http://www.cnblogs.com/Joanna-Yan/p/6878529.html 前面有講到Spring+SpringMVC+MyBatis深入學習及搭建(三)——MyBatis全局配置文件解析 1. 輸入映射 通過parameterType指定輸入參數的類型,類型可 ...


轉載請註明出處: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;
}

測試:

  @Test
    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屬性名之間作一個映射關係。

如果此文對您有幫助,微信打賞我一下吧~ 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.get與post的區別 Get和Post方法都是對伺服器的請求方式,只是他們傳輸表單的方式不一樣。 下麵我們就以傳輸一個表單的數據為例,來分析get與Post的區別 1.1 get方法 jsp中的代碼form表單代碼 1.2 action包中servlet的doGet方法中的代碼 註意:acti ...
  • 一、任務和執行策略之間的隱性耦合 Executor可以將任務的提交和任務的執行策略解耦 只有任務是同類型的且執行時間差別不大,才能發揮最大性能,否則,如將一些耗時長的任務和耗時短的任務放在一個線程池,除非線程池很大,否則會造成死鎖等問題 1.線程饑餓死鎖 類似於:將兩個任務提交給一個單線程池,且兩個 ...
  • 進程與線程 進程:是操作系統結構的基礎;是一個正在執行的程式;電腦中正在運行的程式實例;可以分配給處理器並由處理器執行的一個實體;由單一順序的執行顯示,一個當前狀態和一組相關的系統資源所描述的活動單元。 進程的概念主要有兩點: 第一,進程是一個實體。每一個進程都有它自己的地址空間,一般情況下,包括 ...
  • Map<String,String> a = new HashMap<String,String>(); 然後把值put進去的時候,值不是按照put的順序排序。 Map<String,String> a = new LinkedHashMap<String,String>(); 然後把值put進去, ...
  • 所有 XML 文檔中的文本均會被解析器解析。 只有 CDATA 區段(CDATA section)中的文本會被解析器忽略。 PCDATA PCDATA 指的是被解析的字元數據(Parsed Character Data)。 XML 解析器通常會解析 XML 文檔中所有的文本。 當某個 XML 元素被 ...
  • Java IO學習筆記總結 前言 前面的八篇文章詳細的講述了Java IO的操作方法,文章列表如下 "基本的文件操作" "字元流和位元組流的操作" "InputStreamReader和OutputStreamWriter操作" "記憶體操作流" "管道流" "列印流" "System對IO的支持" " ...
  • 今天面試時遇到的一個演算法題,要求對一個number進行倒置,當時在紙上回答的有點小瑕疵,回來特意完善了下,已調試通過,希望給以後面試的人有點小幫助,下麵附上代碼: ...
  • BufferedReader和BufferedWriter 這兩個類是高效率的提高文件的讀取速度,它們為字元輸入和輸出提供了一個緩衝區,可以顯著的調高寫入和讀取的速度,特別針對大量的磁碟文件讀取的時候,下麵著重的講講這兩個類 BufferedReader 從字元輸入流中讀取文本,緩衝各個字元,從而實 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...