Mybatis是咱們經常使用到的數據層訪問框架,在一般的開發過程當中,咱們通常是使用它的默認的緩存配置。這裏的話咱們簡單的分析一下Mybatis的緩存機制。java
在程序的運行過程當中,咱們有可能在一次的數據庫會話中,執行屢次查詢條件徹底相同的查詢語句,這時候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
咱們前面講到的一級緩存,它的共享範圍就是在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來解決問題,後面有機會會再續寫上:)