Mybatis快取詳解

ckxllf發表於2019-09-10

  什麼是Mybatis快取?

  使用快取可以減少Java Application與資料庫的互動次數,從而提升程式的執行效率。比如,查詢id=1的user物件,第一次查詢出來之後,會自動將該物件儲存到快取中。下一次查詢該物件時,就可以直接從快取中獲取,不需要傳送SQL查詢資料庫了。

  Mybatis快取分類

  一級快取:SqlSession級別,預設開啟,且不能關閉。

  mybatis的一級快取是SqlSession級別的快取,在運算元據庫時需要構造SqlSession物件,在物件中有一個HashMap用於儲存快取資料,不同的SqlSession之間快取資料區域(HashMap)是互相不影響的。

  一級快取的作用域是SqlSession範圍的,當在同一個SqlSession中執行兩次相同的sql語句時,第一次執行完畢會將資料庫中查詢的資料寫到快取(記憶體)中,第二次查詢時會從快取中獲取資料,不再去底層進行資料庫查詢,從而提高了查詢效率。需要注意的是:如果SqlSession執行了DML操作(insert、update、delete),並執行commit()操作,mybatis則會清空SqlSession中的一級快取,這樣做的目的是為了保證快取資料中儲存的是最新的資訊,避免出現髒讀現象。

  當一個SqlSession結束後該SqlSession中的一級快取也就不存在了,Mybatis預設開啟一級快取,不需要進行任何配置。

  二級快取:Mapper級別,預設關閉,可以開啟。

  二級快取是Mapper級別的快取,使用二級快取時,多個SqlSession使用同一個Mapper的sql語句去運算元據庫,得到的資料會存在二級快取區域,它同樣是使用HashMap進行資料儲存,相比一級快取SqlSession,二級快取的範圍更大,多個SqlSession可以共用二級快取,二級快取是跨SqlSession的。

  二級快取是多個SqlSession共享的,其作用域是mapper的同一個namespace,不同的SqlSession兩次執行相同的namespace下的sql語句,且向sql中傳遞的引數也相同,即最終執行相同的sql語句,則第一次執行完畢會將資料庫中查詢的資料寫到快取(記憶體),第二次查詢時會從快取中獲取資料,不再去底層資料庫查詢,從而提高查詢效率。

  Mybatis預設關閉二級快取,可以在setting全域性引數中配置開啟二級快取。

  下面我們透過程式碼來學習如何使用MyBatis快取。

  首先來演示一級快取,以查詢Student物件為例。

  /**

  * @ClassName Student

  * @Description

  * @Author lzq

  * @Date 2019/7/26 13:53

  * @Version 1.0

  **/

  public class Student {

  private int SID;

  private String Sname;

  private String Ssex;

  private int Age;

  public int getSID() {

  return SID;

  }

  public void setSID(int SID) {

  this.SID = SID;

  }

  public String getSname() {

  return Sname;

  }

  public void setSname(String sname) {

  Sname = sname;

  }

  public String getSsex() {

  return Ssex;

  }

  public void setSsex(String ssex) {

  Ssex = ssex;

  }

  public int getAge() {

  return Age;

  }

  public void setAge(int age) {

  Age = age;

  }

  @Override

  public String toString() {

  return "[id"+SID+" 名字"+Sname+" 性別"+Ssex+" 年齡"+Age+"]";

  }

  }

  StudentMapper介面:

  import org.apache.ibatis.annotations.*;

  public interface StudentMapper {

  public Student getStudentById(int id);

  }

  mybatis-config.xml:

  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

  "

  StudentMapper.xml:

  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

  "

  select * from student where SID = #{id}

  測試程式碼:

  **

  * @ClassName Test

  * @Description

  * @Author lzq

  * @Date 2019/7/26 13:53

  * @Version 1.0

  **/

  public class Test {

  public static void main(String[] args) throws IOException {

  String resource = "mybatis-config.xml";

  //讀取配置檔案

  InputStream asStream = Resources.getResourceAsStream(resource);

  //建立sqlSessionFactory

  SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(asStream);

  //建立sqlSession

  SqlSession sqlSession = sqlSessionFactory.openSession();

  //透過動態代理產生StudentMapper物件

  StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

  //查詢id為1的元組

  Student student = mapper.getStudentById(1);

  System.out.println(student);

  Student student1 = mapper.getStudentById(1);

  System.out.println(student1);

  }

  }

  可以看到結果,執行了一次SQL語句,查詢出兩個物件,第一個物件是透過SQL查詢的,並儲存到快取中,第二個物件是直接從快取中獲取的。

  我們說過一級快取是SqlSession級別的,所以SqlSession一旦關閉,快取也就不復存在了,修改程式碼,再次測試。

  測試程式碼:

  **

  * @ClassName Test

  * @Description

  * @Author lzq

  * @Date 2019/7/26 13:53

  * @Version 1.0

  **/

  public class Test {

  public static void main(String[] args) throws IOException {

  String resource = "mybatis-config.xml";

  //讀取配置檔案

  InputStream asStream = Resources.getResourceAsStream(resource);

  //建立sqlSessionFactory

  SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(asStream);

  //建立sqlSession

  SqlSession sqlSession = sqlSessionFactory.openSession();

  //透過動態代理產生StudentMapper物件

  StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

  //查詢id為2的元組

  Student student = mapper.getStudentById(1);

  System.out.println(student);

  sqlSession.close(); //關閉原有的sqlSession

  sqlSession = sqlSessionFactory.openSession(); //建立一個新的

  mapper = sqlSession.getMapper(StudentMapper.class);

  Student student1 = mapper.getStudentById(1);

  System.out.println(student1);

  }

  }

  可以看到,執行了兩次SQL。

  在關閉SqlSession,一級快取失效的情況下,可以啟用二級快取,實現提升效率的要求。

  MyBatis可以使用自帶的二級快取,也可以使用第三方的ehcache二級快取。

  自帶二級快取 無錫人流哪家好

  mybatis-config.xml配置開啟二級快取

  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

  "

  在StudentMapper.xml配置中開啟二級快取:

  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

  "

  select * from student where SID = #{id}

  Student類實現Serializable介面:

  import java.io.Serializable;

  /**

  * @ClassName Student

  * @Description

  * @Author lzq

  * @Date 2019/7/26 13:53

  * @Version 1.0

  **/

  public class Student implements Serializable{

  private int SID;

  private String Sname;

  private String Ssex;

  private int Age;

  public int getSID() {

  return SID;

  }

  public void setSID(int SID) {

  this.SID = SID;

  }

  public String getSname() {

  return Sname;

  }

  public void setSname(String sname) {

  Sname = sname;

  }

  public String getSsex() {

  return Ssex;

  }

  public void setSsex(String ssex) {

  Ssex = ssex;

  }

  public int getAge() {

  return Age;

  }

  public void setAge(int age) {

  Age = age;

  }

  @Override

  public String toString() {

  return "[id"+SID+" 名字"+Sname+" 性別"+Ssex+" 年齡"+Age+"]";

  }

  }

  測試程式碼依舊是上一次用的那個:

  可以看到,執行了一次SQL,查詢出兩個物件,cache命中率為0.5;


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69945560/viewspace-2656601/,如需轉載,請註明出處,否則將追究法律責任。

相關文章