1.mybatis框架執行過程:
1、配置mybatis的配置文件,SqlMapConfig.xml(名稱不固定)
2、通過配置文件,加載mybatis運行環境,創建SqlSessionFactory會話工廠,SqlSessionFactory在實際使用時按單例方式。
3、通過SqlSessionFactory創建SqlSession。SqlSession是一個面向用戶接口(提供操作數據庫方法),實現對象是線程不安全的,建議sqlSession應用場合在方法體內。
4、調用sqlSession的方法去操作數據。如果需要提交事務,需要執行SqlSession的commit()方法。
5、釋放資源,關閉SqlSession
2.一般如果要擴展pojo屬性可以用resultType和resultMap
需求:查詢訂單信息,關聯查詢創建訂單的用戶信息
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類。
2)使用resultMap
a.在Orders類中添加user
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定義:
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中,訂單信息的就是重複。
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
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
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(關聯查詢用戶信息)
3、延遲加載resultMap
使用association中的select指定延遲加載去執行的statement的id。
<!--延遲加載的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:指定延遲加載需要執行的statement的id(是根據user_id查詢用戶信息的statement)
要使用userMapper.xml中findUserById完成根據用戶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中配置
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的包
<diskStorepath=""/>指如果要存入磁盤,的存放路徑
9.緩存的算法
FIFO(First in First out)先進先出。核心原則:如果一個數據最先進入緩存中,則應該最早淘汰掉。
LFU(Least Frequently Used)最近最少使用。如果一個數據在最近一段時間內使用次數很少,那麼在將來一段時間內被使用的可能性也很小。
LRU(Least Recently Used)最近最久未使用。如果一個數據在最近一段時間沒有被訪問到,那麼在將來它被訪問的可能性也很小。
LFU是指使用頻率上,LRU使用時間
10.spring整合mybatis
1)整合原生dao方法
a.在自己的xml方法寫SQL語句
d.do接口的實現類
dao接口實現類需要注入SqlSessoinFactory,通過spring進行注入。
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創建代理對象