spring和mybatis中的連線池和快取

ning12發表於2024-06-11

目錄
  • 十、連線池
    • 10.1連線池
    • 10.2、mybatis連線池的分類
  • 十一、mybatis的快取
    • 一級快取和二級快取
    • 使用一級快取失效的四種情況:
      • 11.1、不同的SqlSession對應不同的一級快取。
      • 11.2、MyBatis的二級快取
    • 二級快取開啟的條件:
      • 11、3二級快取的相關配置
      • 11.4、mybatis快取查詢的順序
      • 11.5整合第三方的快取EhCache

十、連線池

10.1連線池

  1. 連線池是什麼:儲存連線的容器

  2. 解決了什麼問題

    • 如果沒有連線池,每次執行sql語句都需要建立connection的連線,會浪費時間,影響程式的效能。
  3. 提前建立一些連線,儲存到連線池中,使用的時候從連線池獲取連線即可

  4. 常用的連線池

    1. c3p0

    2. dbcp

    3. druid(阿里)

  5. 連線池有歸還的操作,已經對close方法進行了增強,原來是關閉連線,現在是歸還

10.2、mybatis連線池的分類

  1. 在解析mybatis-config.xml配置檔案的時候,建立dataSource物件,存入到Environment物件中。

  2. 當執行SQL語句的時候,準備從dataSource物件中獲取連結。

十一、mybatis的快取

一級快取和二級快取

一級快取是SqlSession級別的,透過同一個SqlSession查詢的資料會被快取,下次查詢相同的資料,就會從一級快取中直接獲取,不會從資料庫重新查詢。一級快取預設是開啟

使用一級快取失效的四種情況:

11.1、不同的SqlSession對應不同的一級快取。

@Test
public void testGetEmpById(){
    SqlSession sqlSession1 = SqlSessionUtil.getSqlSession();
    System.out.println(sqlSession1);
    SqlSession sqlSession2 = SqlSessionUtil.getSqlSession();
    System.out.println(sqlSession2);

    EmpMapper empMapper1 = sqlSession1.getMapper(EmpMapper.class);
    Emp emp1 = empMapper1.getEmpById(1);
    System.out.println(emp1);
    System.out.println("-----------------------------------");
    EmpMapper empMapper2 = sqlSession2.getMapper(EmpMapper.class);
    Emp emp2 = empMapper2.getEmpById(1);
    System.out.println(emp2);
}

2、同一個SqlSession但是查詢條件不同。

3、同一個SqlSession兩次查詢之間,執行了任何一次增刪改操作

Emp emp1 = empMapper.getEmpById(1);
System.out.println(emp1);

empMapper.insertEmp(new Emp(null,"小張",23,"男"));

Emp emp2 = empMapper.getEmpById(1);
System.out.println(emp2);

4、同一個SqlSession兩次查詢之間,手動清空了快取

//手動清空一級快取
sqlSession.clearCache();

11.2、MyBatis的二級快取

二級快取是SqlSessionFactory級別的,透過同一個SqlSessionFactory建立的SqlSession查詢的結果都會被快取;下次查詢相同的資料,就會從二級快取中直接獲取,不會從資料庫重新查詢。二級快取預設是不開啟的

二級快取開啟的條件:

1、在核心配置檔案中,設定全域性配置屬性cacheEnabled=”true” ,預設為true。所以不需要設定

2、在對映檔案中設定標籤

3、二級快取必須在SqlSession關閉之後生效

4、查詢的資料所轉換的實體類型別必須實現序列化的介面

public class Emp implements Serializable 
@Test
public void testCache() throws IOException {
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
    /*sqlSession1和sqlSession2都是sqlSessionFactory建立的*/
    SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
    EmpMapper empMapper1 = sqlSession1.getMapper(EmpMapper.class);
    Emp emp1 = empMapper1.getEmpById(1);
    System.out.println(emp1);
    sqlSession1.close();
    System.out.println("-----------------------");

    SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
    EmpMapper empMapper2 = sqlSession2.getMapper(EmpMapper.class);
    Emp emp2 = empMapper2.getEmpById(1);
    System.out.println(emp2);
    sqlSession2.close();
}


Cache Hit Ratio:二級快取命中率,不為0,說明程式直接從二級快取中獲取了資料

使二級快取失效的情況:

兩次查詢之間執行了任意的增刪改,會使一級和二級快取同時失效

11、3二級快取的相關配置

在mapper配置檔案中新增的cache標籤可以設定一些屬性:

①eviction屬性:快取回收策略,預設的是 LRU。

LRU(Least Recently Used) – 最近最少使用的:移除最長時間不被使用的物件。

FIFO(First in First out) – 先進先出:按物件進入快取的順序來移除它們。

SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的物件。

WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的物件。

②flushInterval屬性:重新整理間隔,單位毫秒

預設情況是不設定,也就是沒有重新整理間隔,快取僅僅呼叫語句時重新整理

③size屬性:引用數目,正整數代表快取最多可以儲存多少個物件,太大容易導致記憶體溢位

④readOnly屬性:只讀, true/false

true:只讀快取;會給所有呼叫者返回快取物件的相同例項。因此這些物件不能被修改。這提供了很重要的效能優勢。

false:讀寫快取;會返回快取物件的複製(透過序列化)。這會慢一些,但是安全,因此預設是false。

11.4、mybatis快取查詢的順序

先查詢二級快取,因為二級快取中可能會有其他程式已經查出來的資料,可以拿來直接使用。

如果二級快取沒有命中,再查詢一級快取

如果一級快取也沒有命中,則查詢資料庫

SqlSession關閉之後,一級快取中的資料會寫入二級快取

11.5整合第三方的快取EhCache

11.5.1新增依賴

<!-- Mybatis EHCache整合包 -->
<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.2.1</version>
</dependency>
<!-- slf4j日誌門面的一個具體實現 -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>	

11.5.2各jar的功能

jar包名稱 作用
mybatis-ehcache Mybatis和EHCache的整合包
ehcache EHCache核心包
slf4j-api SLF4J日誌門面包
logback-classic 支援SLF4J門面介面的一個具體實現

11.5.3建立EHCache配置檔案ehcache.xml

<?xml version="1.0" encoding="utf-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    <!-- 磁碟儲存路徑 -->
    <diskStore path="D:\qingcheng\ehcache"/>
    <defaultCache
            maxElementsInMemory="1000"
            maxElementsOnDisk="10000000"
            eternal="false"
            overflowToDisk="true"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
    </defaultCache>
</ehcache>

11.5.4設定二級快取的型別

<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

11.5.5加入logback日誌

存在SLF4J時,作為簡易日誌的log4j將失效,此時需要藉助SLF4J的具體實現logback來列印日誌,建立logback的配置檔案logback.xml

11.5.6EHCache配置檔案說明

屬性名 是否必須 作用
maxElementsInMemory 在記憶體中快取的element的最大數目
maxElementsOnDisk 在磁碟上快取的element的最大數目,若是0表示無窮大
eternal 設定快取的elements是否永遠不過期。如果為true,則快取的資料始終有效,如果為false那麼還要根據timeToIdleSeconds、timeToLiveSeconds判斷
overflowToDisk 設定當記憶體快取溢位的時候是否將過期的element快取到磁碟上
timeToIdleSeconds 當快取在EhCache中的資料前後兩次訪問的時間超過timeToIdleSeconds的屬性取值時,這些資料便會刪除,預設值是0,也就是可閒置時間無窮大
timeToLiveSeconds 快取element的有效生命期,預設是0.,也就是element存活時間無窮大
diskSpoolBufferSizeMB DiskStore(磁碟快取)的快取區大小。預設是30MB。每個Cache都應該有自己的一個緩衝區
diskPersistent 在VM重啟的時候是否啟用磁碟儲存EhCache中的資料,預設是false。
diskExpiryThreadIntervalSeconds 磁碟快取的清理執行緒執行間隔,預設是120秒。每個120s,相應的執行緒會進行一次EhCache中資料的清理工作
memoryStoreEvictionPolicy 當記憶體快取達到最大,有新的element加入的時候,移除快取中element的策略。預設是LRU(最近最少使用),可選的有LFU(最不常使用)和FIFO(先進先出)

11.5.7 測試還用之前的測試方法即可

相關文章