MyBatis學習筆記(2)—映射關係篇

MyBatis學習筆記(1)—使用篇

MyBatis學習筆記(2)—映射關係篇sql

MyBatis學習筆記(3)—高級映射之一對一映射數據庫

Mybatis學習筆記(4)-高級映射之一對多映射緩存

Mybatis學習筆記(5)-高級映射之多對多映射bash

...敬請期待session

經過上一篇的入門MyBatis學習筆記(1)—使用篇,能夠發現除了一些基本配置外,Mybatis的精華就在於Mapper(映射)部分。Mybatis是針對映射器構造的SQL構建的輕量級框架,而且能夠經過配置生成對應的JavaBean給調用者。在Mybatis中能夠靈活使用SQL來知足各類不一樣場景的需求,因此在互聯網企業內更偏心於使用Mybatis來應對高速變化的需求,而傳統企業更偏向於使用Hibernate。mybatis

映射器的主要元素

上一節咱們僅僅定義了一個select語句:app

<mapper namespace="com.shuqing28.dao.CommodityDao">
    <select id="getAllCommodity" resultType="com.shuqing28.pojo.Commodity">
        SELECT * FROM commodity
    </select>
</mapper>
複製代碼

實際上增刪改查在Mybatis映射器裏面都有對應的元素框架

元素名稱 描述 備註
select 查詢語句,最經常使用的 能夠自定義參數,返回結果集
insert 插入語句 執行後返回一個整數,表明插入的條數
update 更新語句 執行後返回一個整數,表明更新的條數
delete 刪除語句 執行後返回一個整數,表明刪除的條數
parameterMap 定義參數映射關係 即將被刪除的元素,不建議使用
sql 容許定義一部分的SQL,而後在各個地方引用 例如,定義一個表名,在其它地方的SQL語句中使用
resultMap 用來描述從數據庫結果集中加載對象 它將提供映射規則
cache 給定命名空間的緩存配置 ————
cache-ref 其餘命名空間緩存配置的引用 ————

下面咱們探究主要使用的幾個元素post

select

select元素是咱們最經常使用的元素,正如在SQL裏是查詢功能也是最主要的功能之一。在咱們常識裏,查詢語句一般都是根據一個或者多個條件,查詢數據庫返回一個,多個或者全部字段。以前咱們舉得getAllCommodity沒有查詢條件,返回全部字段。學習

在Mybatis裏,咱們能夠傳入簡單的參數類型,像int,float,String這些,也能夠傳入一些複雜的類型,好比JavaBean、Map之流的,Mybatis把這些參數轉換成SQL語句須要的類型後,返回結果,而且經過映射,將結果集自動綁定到JavaBean中,因此JDBC裏面那一套一個一個從ResultSet獲取值的操做都被省略了。

下面咱們看一個有參數的select語句:

<select id="getCommodityById" parameterType="int" resultType="com.shuqing28.pojo.Commodity">
            SELECT * FROM commodity where id=#{id}
</select>
複製代碼

同時咱們定義了接口方法:

Commodity getCommodityById(Integer id);
複製代碼

不一樣於getAllCommodity沒有傳入參數,getCommodityById有一個int類型的傳入參數,返回的仍是Commodity。 上面的select語句包含如下屬性:

  • id標識了這條sql,id與接口名保持一致
  • parameterType定義參數類型,這裏就是int
  • resultType定義了返回值類型,這裏是咱們定義的POJO類

這裏看resultType,咱們查詢的是commodity的全部字段,再次回顧字段定義:

字段名 類型
id int
name varchar(255)
price decimal(8,2)
description varchar(255)

而咱們的POJO類包含:

private Integer id;
private String name;
private Double price;
private String description;
複製代碼

這裏Mybatis幫咱們完成了自動映射,只要返回的SQL列名和JavaBean的屬性一致,Mybatis就能夠幫助咱們自動回填這些字段而無需任何配置。咱們能夠再Mybatis的配置文件裏,經過autoMappingBehavior來設置自動映射,它包含3個值:

  • NONE:取消自動映射
  • PARTIAL:這也是默認值,只會自動映射,沒有定義嵌套結果集映射的結果集
  • FULL:會自動映射任意複雜的結果集(不管是否嵌套)

剛纔咱們舉例的是隻傳遞了一個參數,若是傳遞多個參數呢?這時候就要說說輸入映射了。

輸入映射

傳遞多個參數一般來講有3種方式,經過Map,經過註解,以及經過POJO對象

經過Map傳遞參數

假設咱們想查詢帶有的食物,而且價格低於80的。那麼咱們能夠這麼寫SQL語句

<select id="getCommodityByMap" parameterType="map" resultType="com.shuqing28.pojo.Commodity">
                SELECT * FROM commodity WHERE name like '%${name}%' AND price&lt;#{price}
        </select>
複製代碼

由於mybatis使用xml定義Mapper,因此這裏'<'用了轉義符&lt;表示,其實仍是同樣的。 parameterType定義爲map,咱們定義的接口也是接受Map做爲參數

List<Commodity> getCommodityByMap(Map<String, Object> params);
複製代碼

使用:

CommodityDao commodityDao = sqlSession.getMapper(CommodityDao.class);
Map<String, Object> paramsMap = new HashMap<String , Object>();
paramsMap.put("name", "餅");
paramsMap.put("price", 80.0);
List<Commodity> commodities = commodityDao.getCommodityByMap(paramsMap);
複製代碼

最後打印commodities:

[Commodity{id=1001, name='野葡萄烤餅', price=10.0, description='吃完還有點餓'}, Commodity{id=1003, name='南瓜百吉餅', price=50.0, description='份大量足,能夠去很遠的地方'}]
複製代碼

雖然Map很簡單,可是光是看傳入參數Map,你不知道包含了怎樣的內容,如果深刻還得看如何設置Map的,並且使用時還要一項項指定Map的Key的名字,因此不怎麼提倡使用了。

使用註解方式傳遞參數

註解方式使用了**@Param**註解,咱們這樣定義接口:

List<Commodity> getCommodityByAnnation(@Param("name") String name, @Param("price") Double price);
複製代碼

Mybatis根據@Param提供的名稱,把變量值傳到SQL語句中對應的參數中,參數的可讀性大大提升,可是不足之處在於,如果參數不少,一個一個寫很麻煩,下降了可讀性。

因此最常用的仍是利用POJO傳遞參數。

使用POJO傳遞參數

一般咱們只須要傳遞簡單的POJO對象就能夠了,好比咱們這樣定義select元素:

<select id="getCommodityByPOJO" parameterType="com.shuqing28.pojo.Commodity" resultType="com.shuqing28.pojo.Commodity">
    SELECT * FROM commodity WHERE name like '%${name}%' AND price&lt;#{price}
</select>
複製代碼

測試:

@Test
public void getLowPriceCommodityByPOJO(){
    SqlSession sqlSession = sqlSessionFactory.openSession();
    try {
        CommodityDao commodityDao = sqlSession.getMapper(CommodityDao.class);
        Commodity commodity = new Commodity();
        commodity.setName("餅");
        commodity.setPrice(80.0);
        List<Commodity> commodities = commodityDao.getCommodityByPOJO(commodity);
        System.out.println(commodities);
    } finally {
        sqlSession.close();
    }
}
複製代碼

也會返回和上面同樣的結果,這裏Mybatis會把POJO裏對應的屬性值傳到SQL裏,而後返回結果,注意看傳入參數就是POJO的徹底限定名,和ResultType是同樣的,其實能夠經過別名減小名稱的長度,咱們只須要在mybatis-config.xml中的configuration中定義:

<typeAliases>
        <typeAlias alias="commodity" type="com.shuqing28.pojo.Commodity" />
</typeAliases>
複製代碼

就能夠用commodity替換全部的全稱了,可是不能有重名的,不然會出錯。

有些負責的狀況,咱們須要定義POJO做爲查詢參數,好比上面的例子,你只須要兩個輸入參數,你也能夠定製一個只包含這兩個參數的POJO。

public class CommodityCustom {
    private String name;
    private Double price;
複製代碼

固然使用過程仍是同樣的,定義本身包裝過的POJO一般用來解決傳入查詢條件很複雜的狀況,好比設計到幾張表聯查的,這時候原先定義的POJO解決不了問題,就須要定義一些複合的POJO。

在輸入參數中還有個常常被提到的問題,即#和$的區別

#和$的區別

Mybatis自己是基於JDBC封裝的。因此#{para}是預編譯處理(PreparedStatement),至關於原來的?,而${para}是字符串替換。Mybatis在處理#時,會調用PreparedStatementset系列方法來賦值;處理$時,就是把${para}替換成變量的值。#方式可以很大程度防止sql注入,$方式通常用於傳入數據庫對象,例如傳入表名,通常能用#的就別用$.

說完輸入咱們說輸出映射。

輸出映射

MyBatis的輸出映射分爲兩種方式,resultType和resultMap

resultType

咱們上面全部的例子裏都是定義的resultType,resultType能夠是簡單類型,好比咱們想獲取商品數量啊之類的,還有就是輸出POJO對象或者POJO列表。

不論是POJO對象仍是POJO列表,咱們在resultType中的定義都是同樣的,只不過接口定義不同:

單個對象
Commodity getCommodityById(Integer id);
複製代碼

Mybatis根據接口返回值判斷返回一條對象,若是用過ibatis的能夠知道內部調用了session.selectOne。

返回列表
List<Commodity> getCommodityByPOJO(Commodity commodity);
複製代碼

內部使用session.selectList,Mapper接口使用List<XXX>做爲返回值。

查詢出來的列名和POJO屬性只要有一個一致就會建立POJO對象,頂多別的字段爲默認值,可是若是所有不一致,就不會建立該POJO對象了。

resultMap

上面的resultType在查詢的列名和POJO屬性值一致的時候才能夠映射成功,若是不一致的話,就須要resultMap登場表演了。

若是查詢出來的列名和POJO的屬性名不一致,經過定義一個resultMap對列名和POJO屬性名之間做一個映射關係。

在使用resultMap前咱們須要定義resultMap 假設咱們查詢商品類的兩個字段id和name,可是查詢的時候定義爲id_name_。列名和屬性名不一致了,先定義resultMap

<resultMap id="commodityResultMap" type="commodity">
    	<id column="id_" property="id"/>
    	<result column="name_" property="name"/>
    </resultMap>
複製代碼

其中

  • id標識這個resultMap
  • type標識映射哪一個POJO裏面的屬性,這裏由於上面說過別名了,因此就是映射的Commodity這個POJO
  • id元素標識這個對象的主鍵,result就是普通字段
  • property表明POJO的屬性名稱
  • column表示數據庫SQL的列名

再看咱們的select元素:

<select id="getCommodityByPrice" parameterType="double" resultMap="commodityResultMap">
       SELECT id id_, name name_ FROM USER WHERE price=#{price}
</select>
複製代碼

使用resultType進行輸出映射時,只有查詢出來的列名和pojo中的屬性名一致,該列才能夠映射成功。若是查詢出來的列名和pojo的屬性名不一致,經過定義一個resultMap對列名和pojo屬性名之間做一個映射關係。 此外,resultMap還能夠作一對多、多對多等高級映射,這些內容將在後續文章中介紹。

insert

insert相對於select簡單不少,下面是往商品表插入一個商品的實例:

<insert id="insertCommodity" useGeneratedKeys="true"
   keyProperty="id">
   insert into commodity (name,price,description)
   values (#{name},#{price},#{description})
</insert>
複製代碼

接口爲:

void insertCommodity(Commodity commodity);
複製代碼

這裏咱們注意到了insert語句裏多了兩個屬性useGeneratedKeyskeyProperty,這裏涉及到的是主鍵回填的概念。

  • useGeneratedKeys:告訴Mybatis是否使用數據庫內置策略生成主鍵
  • keyProperty:告訴Mybatis哪一列是主鍵 這樣咱們無須傳入id值,Mybatis就能夠幫咱們設置主鍵,同時還會回填POJO內的id值,當咱們像下面這樣調用時:
@Test
public void insertCommodity(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    CommodityDao commodityDao = sqlSession.getMapper(CommodityDao.class);
    Commodity commodity = new Commodity();
    //commodity.setId(1005);
    commodity.setName("艾蒿小麥餅");
    commodity.setPrice(100.0);
    commodity.setDescription("像在豔陽下戀愛");
    commodityDao.insertCommodity(commodity);
    System.out.println(commodity.getId());
} finally {
    sqlSession.close();
}
}
複製代碼

經過打印咱們能獲得1005,說明commodity已經具有了id,這就是回填的效果。 在這裏,系統默認的方式是給主鍵值加1,若是咱們想要定義本身的主鍵生成方式,可使用selectKey進行自定義:

<insert id="insertCommodity" useGeneratedKeys="true"
    keyProperty="id">
    <selectKey keyProperty="id" resultType="int" order="BEFORE">
        select if (max(id) is null, 1, max(id) + 2) as newId from commodity
    </selectKey>
    insert into commodity (name,price,description)
    values (#{name},#{price},#{description})
</insert>
複製代碼

這裏咱們定義主鍵值是最大id加2,若是尚未記錄,則初始化爲1。

update和delete

update和的delete都會返回影響的條目數 下面僅僅列出配置的實例:

<update id="updateCommodity" parameterType="commodity">
    update commodity set 
    name=#{name},
    price=#{price},
    description=#{description}
    where id=#{id}
</update>

<delete id="deleteCommodity" parameterType="int">
    delete from commodity where id=#{id}
</delete>
複製代碼

這一節主要介紹了主要的幾個語句的使用,着重介紹了select語句,同時結合select語句說明了Mybatis中輸入映射和輸出映射的內容,其它一些高級的映射內容,留到後面的文章介紹。

相關文章
相關標籤/搜索