3-Mybatis-延遲加載與緩存

延遲加載

1. 需求:

查詢訂單並關聯查詢用戶信息
- 先對orders表進行單表查詢,然後通過外鍵user_id對user表進行查詢
- 定義兩個mapper方法對應的statement

1.1只查詢訂單信息

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

1.2關聯查詢用戶信息

通過查詢到的訂單信息中的user_id來關聯查詢用戶信息

2. SQL

SELECT orders.*,
(SELECT `user`.user_name
    FROM `user` 
    WHERE `user`.user_id = orders.user_id)user_name,
(SELECT `user`.user_birth
    FROM `user` 
    WHERE `user`.user_id = orders.user_id)user_birth
FROM orders

3. mapper.xml

<!-- 延遲加載:查詢訂單並關聯查詢用戶信息 -->
<resultMap type="com.wzw.mybatis.model.Orders" id="OrderAndUserResultMap">
    <!-- 配置訂單信息 -->
    <id column="orders_id" property="orders_id"/>
    <result column="number" property="number"/>
    <!-- <result column="user_id" property="user_id"/> -->
    <!-- 配置用戶信息,實現延遲加載 
        select屬性:指定延遲加載需要執行的statement的id
        column屬性:訂單信息關聯查詢用戶信息查詢的列,user_id
    -->
    <association property="user" javaType="com.wzw.mybatis.model.User" 
    select="com.wzw.mybatis.mapper.UserMapper.selectUserById" column="user_id">
    </association>
</resultMap>
<select id="selectOrdersAndUserLazyLoading" resultMap="OrderAndUserResultMap">
    SELECT * FROM orders
</select>

UserMapper.xml
<mapper namespace="com.wzw.mybatis.mapper.UserMapper">
<!-- 根據user_id查詢用戶信息 -->
    <select id="selectUserById" parameterType="java.lang.Integer" resultType="user">
        SELECT * FROM `user` WHERE user_id = #{id}  
    </select>
</mapper>

4. mapper.java

//延遲加載:查詢訂單並關聯查詢用戶信息
public List<Orders> selectOrdersAndUserLazyLoading() throws IOException;

5. SQLMapConfig.xml延遲加載配置

<!-- 延遲加載 -->
<settings>
    <setting name="lazyLoadingEnabled" value="true"/><!-- 默認false -->
    <setting name="aggressiveLazyLoading" value="false"/><!-- 默認true -->
</settings>

6. 測試代碼

OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
//查詢訂單信息
List<Orders> ordeList = mapper.selectOrdersAndUserLazyLoading();
//對訂單集合遍歷
for (Orders orders : ordeList) {
    //按需加載,查詢用戶信息
    User user = orders.getUser();
    System.out.print(user);
}

緩存

這裏寫圖片描述
一級緩存是SqlSession級別的緩存。在操作數據庫時需要創建SqlSession對象。在SqlSession對象中有一個數據結構(HashMap)用於存儲緩存數據。不同的SqlSession之間的緩存數據區域(HashMap)互不影響。

二級緩存是mapper級別的緩存。多個SqlSession執行同一個mapper的SQL語句,多個SqlSession共用二級緩存,二級緩存是跨SqlSession的。

1. 一級緩存

mybatis默認開啓一級緩存

  • 第一次對user_id=1的用戶進行查詢,首先看一級緩存中是否存在,不存在,此時將查詢信息user存入SqlSession的一級緩存中
  • 此時對user執行更新,刪除等需要SqlSession.commit()操作時,清空SqlSession中一級緩存內的數據
  • 第三次對user_id=1的用戶進行查詢,首先看一級緩存中是否存在,不存在,此時將查詢信息user存入SqlSession的一級緩存中
  • 第四次對user_id=1的用戶進行查詢,發現一級緩存中存在數據,從一級緩存中讀取數據

2. 二級緩存

按mapper區分,每一個mapper都有自己的二級緩存區域,此處mapper按namespace區分。既每一個namespace的mapper有一個二級緩存區域。如果兩個mapper的namespace相同,則執行這兩個mapper中的SQL語句查詢到的數據都存儲在同一個二級緩存中。

2.1 開啓二級緩存

SQLMapConfig.xml

<settings>
    <!-- 延遲加載 -->
    <setting name="lazyLoadingEnabled" value="true"/><!-- 默認false -->
    <setting name="aggressiveLazyLoading" value="false"/><!-- 默認true -->
    <!-- 配置二級緩存,默認開啓 -->
    <setting name="cacheEnabled" value="true"/>
</settings>

UserMapper.xml

<!-- 開啓二級緩存 -->
<cache></cache>

2.2 pojo類實現序列號Serializable

public class User implements Serializable

2.3 禁用二級緩存

useCache=false,在statement中配置該條命令,可禁用二級緩存,默認true。
針對每次查詢都需要最新的數據

<!-- 根據user_id查詢用戶信息 -->
<select id="selectUserById" parameterType="java.lang.Integer" resultType="user" useCache="false">
    SELECT * FROM `user` WHERE user_id = #{id}  
</select>

2.4 刷新緩存(清空緩存)

flushCache=true,默認爲true。在insert、update、delete時,每次操作後需要刷新。避免出現髒讀。

2.5 Cache標籤參數

  • flushInterval(刷新間隔):可設置爲任意的正整數,表示一個毫秒爲單位的時間段。默認不設置(無刷新間隔),緩存在調用語句時刷新。
  • size(引用數目):可以設置爲任意整數,要記住你緩存的對象數目和你運行環境的可用內存資源數目。默認爲1024。
  • readOnly(只讀):true/false。只讀的緩存會給所有調用者返回緩存對象的相同實例。因此這些對象不能被修改。可讀寫的緩存會返回對象的拷貝(通過序列號)。這會慢一些,但是安全,因此默認false。

3 mybatis整合ehcache

Mybatis提供了一個cache接口,如果要實現自己的緩存邏輯,實現cache接口開發即可。
Mybatis和ehcache整合,mybatis和ehcache整合包中提供了一個cache接口的實現類。

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