mybatis的緩存機制

簡介:

  Mybatis是咱們經常使用到的數據層訪問框架,在一般的開發過程當中,咱們通常是使用它的默認的緩存配置。這裏的話咱們簡單的分析一下Mybatis的緩存機制。java

Mybatis的一級緩存:

  在程序的運行過程當中,咱們有可能在一次的數據庫會話中,執行屢次查詢條件徹底相同的查詢語句,這時候Mybatis中的一級緩存就排上了用場,若是是執行相同的SQL語句,會避免直接對數據庫來進行操做,而是從一級緩存中來查詢數據,這樣能夠在必定程度上提升查詢的性能。mysql

  一級緩存的應用範圍是在SqlSession中,當用戶發起松球的時候,Mybatis會根據當前執行的語句生成映射聲明(MappedStatement),而後在Local Cache中進行查詢,若是有緩存中有數據的數就直接返回查詢的結果給用戶。若是緩存中沒有的話,查詢數據庫,而且將結果寫入到Local Cache中,最後將結果返回個用戶。下面作一個基本的案例展現。sql

  User類的代碼以下:數據庫

 1 package com.buwei.entity;
 2 
 3 /**
 4  * @author buwei
 5  * @date 2018/12/20 12:33
 6  */
 7 public class User {
 8     private int id;
 9     private String name;
10     private String password;
11     //   省略getter和setter方法
12 }

  接口UserMapper和對應的映射文件UserMapper.xml的代碼以下:apache

 1 package com.buwei.mapper;
 2 
 3 import com.buwei.entity.User;
 4 import java.util.List;
 5 /**
 6  * @author buwei
 7  * @date 2018/12/20 12:34
 8  */
 9 public interface UserMapper {
10     /**
11      * 查詢全部
12      * @return 返回全部的查詢數據
13      */
14     List<User> findAll();
15 }
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE mapper
 3         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <mapper namespace="com.buwei.mapper.UserMapper">
 6     <!--配置查詢全部-->
 7     <select id="findAll" resultType="com.buwei.entity.User">
 8         select * from user
 9     </select>
10 </mapper>

  主要的配置就是Mybatis的配置文件了,須要配置開啓一級緩存的配置語句,在文件中有相應的註釋,具體配置在第十行:緩存

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE configuration
 3         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <configuration>
 6 
 7     <settings>
 8         <!--控制檯打印日誌-->
 9         <setting name="logImpl" value="STDOUT_LOGGING"/>
10         <!--開啓一級緩存-->
11         <setting name="localCacheScope" value="SESSION"/>
12     </settings>
13     <!--配置mybatis的環境-->
14     <environments default="mysql">
15         <!--配置mysql的環境-->
16         <environment id="mysql">
17             <!--配置事務的類型-->
18             <transactionManager type="JDBC"></transactionManager>
19             <!--配置鏈接數據庫的信息,用的是數據源(鏈接池)-->
20             <dataSource type="POOLED">
21                 <property name="driver" value="com.mysql.jdbc.Driver"/>
22                 <property name="url" value="jdbc:mysql://localhost:3306/mybatiscache"/>
23                 <property name="username" value="root"/>
24                 <property name="password" value="root"/>
25             </dataSource>
26         </environment>
27     </environments>
28 
29 
30     <!--告知mybatis映射配置的位置-->
31     <mappers>
32         <package name="com.buwei.mapper"></package>
33     </mappers>
34 </configuration>

  測試類:MybatisCacheTest,測試建立一個SQLsession的狀況下,連續執行五次查詢,控制檯打印實際的查詢:session

 1 package com.buwei.test;
 2 
 3 import com.buwei.entity.User;
 4 import com.buwei.mapper.UserMapper;
 5 import org.apache.ibatis.io.Resources;
 6 import org.apache.ibatis.session.SqlSession;
 7 import org.apache.ibatis.session.SqlSessionFactory;
 8 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 9 
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.util.List;
13 
14 /**
15  * @author buwei
16  * @date 2018/12/20 12:40
17  */
18 
19 public class MybatisCacheTest {
20 
21     public static void main(String[] args) throws IOException {
22         // 1.讀取配置文件
23         InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml");
24         // 2.建立sqlSessionFactory的構建者對象
25         SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
26         // 3.使用構建者建立工廠對象SQLSessionFactory
27         SqlSessionFactory factory = builder.build(in);
28         // 4.使用SQLSessionFactory生產SQLSession
29         SqlSession session = factory.openSession();
30         // 5.使用session建立mapper的代理對象
31         UserMapper userMapper = session.getMapper(UserMapper.class);
32         // 6使用代理對象執行查詢全部方法
33         for (int i = 0; i < 5; i++) {
34             List<User> list = userMapper.findAll();
35             System.out.println(list);
36         }
37         // 7.釋放資源
38         session.close();
39         in.close();
40     }
41 }

  執行測試方法,咱們會發如今實際的查詢過程當中,只向數據庫執行了一次查詢,控制檯打印以下:mybatis

Mybatis的二級緩存:

  咱們前面講到的一級緩存,它的共享範圍就是在SqlSession中,若是多個SqlSession之間須要共享緩存,這時候就須要使用到二級緩存了。二級緩存的範圍是在namespace中的。開啓了二級緩存以後,執行查詢一級緩存以前,會先查詢二級緩存。app

  開啓二級緩存,咱們須要在Mybatis的配置文件中配置:框架

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

  須要在Mybatis的接口映射文件中配置cache揮着cache-ref,以下:

1 <cache/>

  建立測試類MybatisCacheTest02:

 1 package com.buwei.test;
 2 
 3 import com.buwei.entity.User;
 4 import com.buwei.mapper.UserMapper;
 5 import org.apache.ibatis.io.Resources;
 6 import org.apache.ibatis.session.SqlSession;
 7 import org.apache.ibatis.session.SqlSessionFactory;
 8 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 9 
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.util.List;
13 
14 /**
15  * @author buwei
16  * @date 2018/12/20 12:40
17  */
18 
19 public class MybatisCacheTest02 {
20 
21     public static void main(String[] args) throws IOException {
22         // 1.讀取配置文件
23         InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml");
24         // 2.建立sqlSessionFactory的構建者對象
25         SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
26         // 3.使用構建者建立工廠對象SQLSessionFactory
27         SqlSessionFactory factory = builder.build(in);
28         // 4.使用SQLSessionFactory生產SQLSession
29         SqlSession session01 = factory.openSession();
30         SqlSession session02 = factory.openSession();
31         // 5.使用session建立mapper的代理對象
32         UserMapper userMapper01 = session01.getMapper(UserMapper.class);
33         UserMapper userMapper02 = session02.getMapper(UserMapper.class);
34         // 6使用代理對象執行查詢全部方法
35         for (int i = 0; i < 2; i++) {
36             List<User> list01 = userMapper01.findAll();
37             System.out.println( "userMapper01讀取數據"+ list01);
38         }
39         for (int i = 0; i < 2; i++) {
40             List<User> list02 = userMapper02.findAll();
41             System.out.println("userMapper02讀取數據"+list02);
42         }
43         // 7.釋放資源
44         session02.close();
45         session01.close();
46         in.close();
47     }
48 }

  執行方法以後咱們發如今session沒有執行commit()方法時,二級緩存並無起到做用

  咱們在userMapper01執行了查詢以後執行:

1 session01.commit();

  而後再次執行測試方法:

  從控制檯打印的數據能夠知道,session02的查詢有使用到緩存。

  還有就是當咱們執行了更新數據以後,會清空緩存,這裏就沒有作展現了,有興趣的能夠本身來測試一下。

  二級緩存的範圍是namespace的,而後咱們一般就是一張表的查詢會對應一個映射文件,就是在咱們執行多表查詢的時候有時候不一樣的namespace之間數據更新是感應不到的,這時候就會讀取到髒數據,這時候可使用cache-ref來解決問題,後面有機會會再續寫上:)

相關文章
相關標籤/搜索