Mybatis學習總結五之緩存

MyBatis 是持久層框架,支持一級緩存和二級緩存

mybatis提供查詢緩存,用於減輕數據壓力,提高數據庫性能。

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

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

3. 對於緩存數據更新機制,當某一個作用域(一級緩存/二級緩存)的進行了 C/U/D 操作後,默認該作用域下所有 select 中的緩存將被清空。

一級緩存

 一級緩存是SqlSession級別的緩存。在操作數據庫時需要構造 sqlSession對象,在對象中有一個數據結構(HashMap)用於存儲緩存數據。不同的sqlSession之間的緩存數據區域(HashMap)是互相不影響的。

package com.aiit.test;

import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.aiit.pojo.User;


public class TestMyBatisDemo {
	/*
	 * 一級緩存: 也就Session級的緩存(默認開啓)
	 */
	public static void main(String[] args) {

		String resource="mybatis.cfg.xml";

		InputStream inputStream = TestMyBatisDemo.class.getClassLoader().getResourceAsStream(resource);

		SqlSessionFactory factory = new  SqlSessionFactoryBuilder().build(inputStream);
		SqlSession session = factory.openSession();

		//1.查詢
		String statement1 = "com.aiit.dao.UserMapper.selectOne";
		User user1 = session.selectOne(statement1,1);
		System.out.println("查詢結果1: " + user1);
		 /*
                     必須是同一個Session,如果session對象已經close()過了就不可能用了 
        */
		user1 = session.selectOne(statement1,1);
		System.out.println("查詢結果2: " + user1);
		session.close();
		/**
		 * session被關閉下面代碼就沒有結果,需要重新執行session = factory.openSession();
		 * user1 = session.selectOne(statement1,1);
		   System.out.println("查詢結果3: " + user1); 
		 */
		session = factory.openSession();
		user1 = session.selectOne(statement1,1);
		System.out.println("查詢結果4: " + user1);

  
		//3.修改   執行增刪改時都會自動清除緩存,確保操作後和數據庫一致
		String statement3 = "com.aiit.dao.UserMapper.updateOne";
		User user3 = new User(9, "中國");
		int updateResult = session.update(statement3, user3);
		System.out.println("修改成功"+updateResult);
        session.commit();
		session.close();
	}

}

特別注意的地方:

1.一級緩存: 也就Session級的緩存(默認開啓)

2.  必須是同一個Session,如果session對象已經close()過了就不可能用了,需要重新session = factory.openSession();

3.一旦執行增刪改,緩存將會被清除

二級緩存

 1.在mybatis.cfg.xml中開啓二級緩存

<configuration>
    <settings>
        <!--這個配置使全局的映射器(二級緩存)啓用或禁用緩存-->
        <setting name="cacheEnabled" value="true" />
        .....
    </settings>
    ....
</configuration>

2.UserMapper.xml在映射文件中開啓二級緩存

具體配置 開啓緩存cache、執行緩存useCache、刷新緩存flushCache

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.aiit.dao.UserMapper">

<!--開啓本mapper的namespace下的二級緩存-->
   <cache eviction="LRU" flushInterval="100000" readOnly="true" size="1024"/>

 <!--可以通過設置useCache來規定這個sql是否開啓緩存,ture是開啓,false是關閉-->   
	<select id="selectOne" parameterType="int" resultType="com.aiit.pojo.User"  useCache="true">
		SELECT * FROM tbl_user WHERE tbl_user.id=#{id}
	</select>
	

 <!--刷新二級緩存 flushCache
   <select id="selectOne" parameterType="int" resultType="com.aiit.pojo.User"  flushCache="true">
		SELECT * FROM tbl_user WHERE tbl_user.id=#{id}
	</select>
    -->	
</mapper>

3.使用二級緩存時,User類必須實現一個Serializable接口===> User implements Serializable

4.測試二級緩存
     使用兩個不同的SqlSession對象去執行相同查詢條件的查詢,第二次查詢時不會再發送SQL語句,而是直接從緩存中取出數據

package com.aiit.test;

import java.io.InputStream;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.aiit.pojo.User;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		String resource="mybatis.cfg.xml";
		InputStream inputStream = Test.class.getClassLoader().getResourceAsStream(resource);
		SqlSessionFactory factory = new  SqlSessionFactoryBuilder().build(inputStream);
		//開啓兩個不同的SqlSession
		
		SqlSession session1 = factory.openSession();
		SqlSession session2 = factory.openSession();
		
		String statement1 = "com.aiit.dao.UserMapper.selectOne";			
		User user1 = session1.selectOne(statement1,1);				
		//一定要提交事務之後二級緩存纔會起作用		
		 session1.commit();	
		System.out.println("查詢結果1: " + user1);
		
	    //由於使用的是兩個不同的SqlSession對象,所以即使查詢條件相同,一級緩存也不會開啓使用	
		user1 = session2.selectOne(statement1,1);	
		System.out.println("查詢結果1: " + user1);
	}

}

5.驗證我們可以根據兩條查詢語句的時間,查看是否執行緩存

long startTime = System.currentTimeMillis();    //獲取開始時間

User user1 = session1.selectOne(statement1,1);    //測試的代碼段

long endTime = System.currentTimeMillis();    //獲取結束時間
long time = endTime - startTime ;
System.out.println("查詢時間: " + time );

特別注意:

    1. 映射語句文件中的所有select語句將會被緩存。

  2. 映射語句文件中的所有insert,update和delete語句會刷新緩存。

  3. 緩存會使用Least Recently Used(LRU,最近最少使用的)算法來收回。

  4. 緩存會根據指定的時間間隔來刷新。

  5. 緩存會存儲1024個對象

cache標籤

<cache 
eviction="FIFO"  <!--回收策略爲先進先出-->
flushInterval="60000" <!--自動刷新時間60s-->
size="512" <!--最多緩存512個引用對象-->
readOnly="true"/> <!--只讀-->

1.eviction:代表的是緩存回收策略,目前MyBatis提供以下策略。 

     (1) LRU,最近最少使用的,一處最長時間不用的對象

     (2) FIFO,先進先出,按對象進入緩存的順序來移除他們  

     (3) SOFT,軟引用,移除基於垃圾回收器狀態和軟引用規則的對象

     (4) WEAK,弱引用,更積極的移除基於垃圾收集器狀態和弱引用規則的對象。這裏採用的是LRU,移除最長時間不用的對形象

2. flushInterval:刷新間隔時間,單位爲毫秒,這裏配置的是100秒刷新,如果你不配置它,那麼當SQL被執行的時候纔會去刷新緩存。

 3.size:引用數目,一個正整數,代表緩存最多可以存儲多少個對象,不宜設置過大。設置過大會導致內存溢出。

 4. readOnly:只讀,意味着緩存數據只能讀取而不能修改,這樣設置的好處是我們可以快速讀取緩存,缺點是我們沒有辦法修改緩存,他的默認值是false,不允許我們修改。

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