mybatis進階

1.mybatis框架執行過程:

1、配置mybatis的配置文件,SqlMapConfig.xml(名稱不固定)

2、通過配置文件,加載mybatis運行環境,創建SqlSessionFactory會話工廠,SqlSessionFactory在實際使用時按單例方式。

3、通過SqlSessionFactory創建SqlSession。SqlSession是一個面向用戶接口(提供操作數據庫方法),實現對象是線程不安全的,建議sqlSession應用場合在方法體內。

4、調用sqlSession的方法去操作數據。如果需要提交事務,需要執行SqlSession的commit()方法。

5、釋放資源,關閉SqlSession

2.一般如果要擴展pojo屬性可以用resultTyperesultMap

需求:查詢訂單信息,關聯查詢創建訂單的用戶信息

1)使用resultType

a.SQL語句。確定查詢的主表:訂單表

確定查詢的關聯表:用戶表,由於orders表中有一個外鍵(user_id),通過外鍵關聯查詢用戶表只能查詢出一條記錄,可以使用內鏈接。

SELECT

  orders.*,

  USER.username,

  USER.sex,

  USER.address

FROM

  orders,

  USER

WHERE orders.user_id = user.id

b.創建pojo類

將上邊sql查詢的結果映射到pojo中,pojo中必須包括所有查詢列名。原始的Orders.java不能映射全部字段,需要新創建的pojo。創建 一個pojo繼承包括查詢字段較多的po類。

wKioL1YbZ-6T0RRjAAKKKIWcmQA108.jpg

2)使用resultMap

a.在Orders類中添加user

wKiom1YbaCrCas7ZAADlVIKbGJs495.jpg

b.mapper.xml

定義resultMap:

<!-- 訂單查詢關聯用戶的resultMap

  將整個查詢的結果映射到cn.itcast.mybatis.po.Orders

   -->

  <resultMap type="cn.itcast.mybatis.po.Orders"id="OrdersUserResultMap">

     <!-- 配置映射的訂單信息 -->

     <!-- id:指定查詢列中的唯一標識,訂單信息的中的唯一標識,如果有多個列組成唯一標識,配置多個id

        column:訂單信息的唯一標識

        property訂單信息的唯一標識列所映射到Orders中哪個屬性

       -->

     <id column="id" property="id"/>

     <result column="user_id"property="userId"/>

     <result column="number"property="number"/>

     <result column="createtime"property="createtime"/>

     <result column="note"property=note/>

    

     <!-- 配置映射的關聯的用戶信息 -->

     <!-- association:用於映射關聯查詢單個對象的信息

     property要將關聯查詢的用戶信息映射到Orders中哪個屬性

      -->

     <association property="user"  javaType="cn.itcast.mybatis.po.User">

        <!-- id:關聯查詢用戶的唯一標識

        column指定唯一標識用戶信息的列

        javaType映射到user的哪個屬性

         -->

        <id column="user_id" property="id"/>

        <result column="username"property="username"/>

        <result column="sex"property="sex"/>

        <result column="address"property="address"/>

    

     </association>

  </resultMap>

statement定義:

wKiom1YbaH2TdoG5AAGjbj_dz9c540.jpg

3.resultType和resultMap實現一對一查詢小結

resultType:使用resultType實現較爲簡單,如果pojo中沒有包括查詢出來的列名,需要增加列名對應的屬性,即可完成映射。如果沒有查詢結果的特殊要求建議使用resultType。

resultMap:需要單獨定義resultMap,實現有點麻煩,如果對查詢結果有特殊的要求,使用resultMap可以完成將關聯查詢映射pojo的屬性中。

resultMap可以實現延遲加載,resultType無法實現延遲加載。

4.一對多

查詢訂單及訂單明細的信息。

確定主查詢表:訂單表    確定關聯查詢表:訂單明細表

在一對一查詢基礎上添加訂單明細表關聯即可。

 

SELECT

  orders.*,

  USER.username,

  USER.sex,

  USER.address,

  orderdetail.id orderdetail_id,

  orderdetail.items_id,

  orderdetail.items_num,

  orderdetail.orders_id

FROM

  orders,

  USER,

  orderdetail

WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id

分析

使用resultType將上邊的查詢結果映射到pojo中,訂單信息的就是重複。

wKioL1YbaPPzhIEyAAN_F6Zos4Q308.jpg

wKiom1YbadOCbMCTAAIhW8oUgRk461.jpg

c.resultMap定義

<!--訂單及訂單明細的resultMap

   使用extends繼承不用在中配置訂單信息和用戶信息的映射

    -->

   <resultMap type="cn.itcast.mybatis.po.Orders"id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap">

      <!-- 訂單信息 -->

      <!-- 用戶信息 -->

      <!-- 使用extends繼承,不用在中配置訂單信息和用戶信息的映射 -->

     

     

      <!-- 訂單明細信息

      一個訂單關聯查詢出了多條明細,要使用collection進行映射

      collection對關聯查詢到多條記錄映射到集合對象中

      property將關聯查詢到多條記錄映射到cn.itcast.mybatis.po.Orders哪個屬性

      ofType:指定映射到list集合屬性中pojo的類型

       -->

       <collection property="orderdetails"ofType="cn.itcast.mybatis.po.Orderdetail">

         <!-- id:訂單明細唯一標識

         property:要將訂單明細的唯一標識映射到cn.itcast.mybatis.po.Orderdetail的哪個屬性

           -->

         <id column="orderdetail_id"property="id"/>

         <result column="items_id"property="itemsId"/>

         <result column="items_num"property="itemsNum"/>

         <result column="orders_id"property="ordersId"/>

       </collection>

     

  

   </resultMap>

d.mapper.java

spacer.gif

5.多對多查詢

需求:查詢用戶及用戶購買商品信息。

查詢主表是:用戶表。關聯表:由於用戶和商品沒有直接關聯,通過訂單和訂單明細進行關聯,所以關聯表:orders、orderdetail、items

 

SELECT

  orders.*,

  USER.username,

  USER.sex,

  USER.address,

  orderdetail.id orderdetail_id,

  orderdetail.items_id,

  orderdetail.items_num,

  orderdetail.orders_id,

  items.name items_name,

  items.detail items_detail,

  items.price items_price

FROM

  orders,

  USER,

  orderdetail,

  items

WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id ANDorderdetail.items_id = items.id

a.mapper.xml

wKioL1YbajGjd3xDAAEEOgYZiRA455.jpg

b.resultMap定義:

映射思路:將用戶信息映射到user中。

在user類中添加訂單列表屬性List<Orders> orderslist,將用戶創建的訂單映射到orderslist

在Orders中添加訂單明細列表屬性List<OrderDetail>orderdetials,將訂單的明細映射到orderdetials

在OrderDetail中添加Items屬性,將訂單明細所對應的商品映射到Items

<!--查詢用戶及購買的商品 -->

   <resultMap type="cn.itcast.mybatis.po.User"id="UserAndItemsResultMap">

      <!-- 用戶信息 -->

      <id column="user_id"property="id"/>

      <result column="username"property="username"/>

      <result column="sex"property="sex"/>

      <result column="address"property="address"/>

      <!-- 訂單信息   一個用戶對應多個訂單,使用collection映射-->

       <collection property="ordersList"ofType="cn.itcast.mybatis.po.Orders">

         <id column="id"property="id"/>

         <result column="user_id"property="userId"/>

         <result column="number" property="number"/>

         <result column="createtime" property="createtime"/>

         <result column="note" property="note"/>

       <!-- 訂單明細  一個訂單包括多個明細 -->

        <collection property="orderdetails"ofType="cn.itcast.mybatis.po.Orderdetail">

                <id column="orderdetail_id" property="id"/>

               <result column="items_id"property="itemsId"/>

               <result column="items_num"property="itemsNum"/>

               <result column="orders_id"property="ordersId"/>       

      <!-- 商品信息  一個訂單明細對應一個商品 -->

           <association property="items"javaType="cn.itcast.mybatis.po.Items">

              <id column="items_id"property="id"/>

              <result column="items_name"property="name"/>

              <result column="items_detail"property="detail"/>

              <result column="items_price"property="price"/>

           </association>    

        </collection>  

       </collection>

   </resultMap>

c.mapper.java

//查詢用戶購買商品信息

public List<User> findUserAndItemsResultMap()throws Exception;

6.resultType與resultMap多對多小結

resultType

作用:將查詢結果按照sql列名pojo屬性名一致性映射到pojo中。

場合:常見一些明細記錄的展示,比如用戶購買商品明細,將關聯查詢信息全部展示在頁面時,此時可直接使用resultType將每一條記錄映射到pojo中,在前端頁面遍歷list(list中是pojo)即可。

resultMap

使用association和collection完成一對一和一對多高級映射(對結果有特殊的映射要求)。

association

作用:將關聯查詢信息映射到一個pojo對象中。

場合:爲了方便查詢關聯信息可以使用association將關聯訂單信息映射爲用戶對象的pojo屬性中,比如:查詢訂單及關聯用戶信息。使用resultType無法將查詢結果映射到pojo對象的pojo屬性中,根據對結果集查詢遍歷的需要選擇使用resultType還是resultMap。  

collection

作用:將關聯查詢信息映射到一個list集合中。

場合:爲了方便查詢遍歷關聯信息可以使用collection將關聯信息映射到list集合中,比如:查詢用戶權限範圍模塊及模塊下的菜單,可使用collection將模塊映射到模塊list中,將菜單列表映射到模塊對象的菜單list屬性中,這樣的作的目的也是方便對查詢結果集進行遍歷查詢。如果使用resultType無法將查詢結果映射到list集合中。

7.延遲加載

resultMap可以實現高級映射(使用association、collection實現一對一及一對多映射),association、collection具備延遲加載功能。使用association實現延遲加載

a.mapper.xml

需要定義兩個mapper的方法對應的statement。

1、只查詢訂單信息

SELECT * FROM orders

在查詢訂單的statement中使用association去延遲加載(執行)下邊的satatement(關聯查詢用戶信息)

wKiom1YbaynSYOvRAAINpqs6l2o554.jpg

3、延遲加載resultMap

使用association中的select指定延遲加載去執行的statementid

 

<!--延遲加載的resultMap -->

   <resultMap type="cn.itcast.mybatis.po.Orders"id="OrdersUserLazyLoadingResultMap">

         <!--對訂單信息進行映射配置  -->

         <id column="id" property="id"/>

         <result column="user_id" property="userId"/>

         <result column="number" property="number"/>

         <result column="createtime" property="createtime"/>

         <result column="note" property="note"/>

   <!-- 實現對用戶信息進行延遲加載

      select指定延遲加載需要執行的statementid是根據user_id查詢用戶信息的statement

      要使用userMapper.xmlfindUserById完成根據用戶id(user_id)用戶信息的查詢如果findUserById不在本mapper中需要前邊加namespace

      column:訂單信息中關聯用戶信息查詢的列,是user_id 關聯查詢的sql理解爲:

      SELECT orders.*,

      (SELECT username FROM USER WHEREorders.user_id = user.id)username,

      (SELECT sex FROM USER WHERE orders.user_id= user.id)sex FROM orders-->

         <association property="user"  javaType="cn.itcast.mybatis.po.User"

          select="cn.itcast.mybatis.mapper.UserMapper.findUserById"column="user_id">

         <!-- 實現對用戶信息進行延遲加載 -->

         </association> 

   </resultMap>

mapper.java

//查詢訂單關聯查詢用戶,用戶信息是延遲加載

public List<Orders> findOrdersUserLazyLoading()throws Exception;

b.測試

1、執行上邊mapper方法(findOrdersUserLazyLoading),內部去調用cn.itcast.mybatis.mapper.OrdersMapperCustom中的findOrdersUserLazyLoading只查詢orders信息(單表)。

2、在程序中去遍歷上一步驟查詢出的List<Orders>,當我們調用Orders中的getUser方法時,開始進行延遲加載。

3、延遲加載,去調用UserMapper.xml中findUserbyId這個方法獲取用戶信息。

延遲加載配置在SqlMapConfig.xml中配置

wKiom1Yba9GT-iTxAAIlddDX9Zc035.jpg

8.緩存

1)mybatis中一級緩存不用配置,一級緩存基於 PerpetualCache 的 HashMap 本地緩存,其存儲作用域爲 Session,當 Session flush 或 close 之後,該Session中的所有 Cache 就將清空。

2)二級緩存與一級緩存其機制相同,默認也是採用 PerpetualCache,HashMap存儲,不同在於其存儲作用域爲 Mapper(Namespace),並且可自定義存儲源,如 Ehcache、Hazelcast等。

a.在覈心配置文件SqlMapConfig.xml中加入

<setting name="cacheEnabled" value="true"/>


描述
允許值
cacheEnabled
對在此配置文件下的所有cache進行全局性開/關設置
true false

b.在單獨的xml文件中配置

<mappernamespace="cn.itcast.mybatis.mapper.UserMapper">

<cache />標籤

但是,爲了提高系統的併發性能,一般對系統進行分佈式部署(集羣部署方式),但是mybatis自身不能對緩存數據進行集中管理,所以需要使用分佈式緩存框架,如redis、memcached、ehcache。

3)mybatis整合ehcache框架

a.加入ehcache的包

wKioL1YbbPfCz6yFAAOXCL8V_R0776.jpg

<diskStorepath=""/>指如果要存入磁盤,的存放路徑

9.緩存的算法

FIFOFirst in First out)先進先出。核心原則:如果一個數據最先進入緩存中,則應該最早淘汰掉。

LFULeast Frequently Used)最近最少使用。如果一個數據在最近一段時間內使用次數很少,那麼在將來一段時間內被使用的可能性也很小。

LRULeast Recently Used)最近最久未使用。如果一個數據在最近一段時間沒有被訪問到,那麼在將來它被訪問的可能性也很小。

LFU是指使用頻率上,LRU使用時間

10.spring整合mybatis

1整合原生dao方法

a.在自己的xml方法寫SQL語句

wKioL1YbbUCQLWMiAAKL2wNDMr0560.jpg

d.do接口的實現類

dao接口實現類需要注入SqlSessoinFactory,通過spring進行注入。

wKioL1YbbaDxyrYVAANc7fDDD20023.jpg

wKiom1Ybbb7hRlWkAADNz26aNNA610.jpg

2)spring與mapper代理整合

a.先寫mapper.java(一系列方法,與dao接口中方法類似)與mapper.xml(SQL語句)。如下爲mapper.java代碼

publicinterface UserMapper {

  

   //用戶信息綜合查詢

   public List<UserCustom> findUserList(UserQueryVouserQueryVo) throws Exception;

  

   //用戶信息綜合查詢總數

   publicint findUserCount(UserQueryVouserQueryVo) throws Exception;

  

   //根據id查詢用戶信息

   public User findUserById(int id) throws Exception;

  

   //根據id查詢用戶信息,使用resultMap輸出

   public User findUserByIdResultMap(int id) throws Exception;

  

  

   //根據用戶名列查詢用戶列表

   public List<User> findUserByName(String name)throws Exception;

  

   //插入用戶

   publicvoid insertUser(User user)throws Exception;

  

   //刪除用戶

   publicvoid deleteUser(int id)throws Exception;

  

   //更新用戶

   publicvoid updateUser(User user)throws Exception;

}

b.通過MapperFactoryBean創建代理對象

wKiom1Ybbg_DLFqvAALv8kjhw0s772.jpg

wKioL1Ybbm2BJYT5AAKaQH9RaAQ089.jpg

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章