浅谈Mybatis的一级缓存和二级缓存
MyBatis的緩存機制
緩存的引入
當我們大量執行重復的查詢SQL語句的時候,會頻繁的和數據庫進行通信,會增加查詢時間等影響用戶體驗的問題,可以通過緩存,以降低網絡流量,使網站加載速度更快.
MyBatis的一級緩存
默認情況下,MyBatis只啟用了本地的會話緩存,它僅僅對一個會話中的數據進行緩存。這也就是大家常說的MyBatis一級緩存,一級緩存的作用域是SqlSession。
第1種情況:同個session進行兩次相同查詢
代碼驗證
//測試一級緩存@Testpublic void testCache() throws IOException {//加載配置文件InputStream rs = Resources.getResourceAsStream("MyBatisConfig.xml");//獲取工廠建造類SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//獲取工廠對象SqlSessionFactory build = sqlSessionFactoryBuilder.build(rs);//獲取SqlSession對象SqlSession sqlSession = build.openSession(true);//得到代理的對象StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);//根據名字查詢Student stu1 = mapper.findStudentByName("小花花");Student stu2 = mapper.findStudentByName("小花花");/*這里相等,說明默認開啟一級緩存,就是在同一個sqlSession域中有效,只要查詢相同的語句,就是從一級緩存中獲取*/System.out.println("兩次查詢結果的學生對象是否是同一個:"+(stu1==stu2));//關閉會話sqlSession.close();rs.close();}執行結果
由上面的執行結果得知
MyBatis是默認開啟一級緩存的,作用域是同一個SqlSession,在同一個sqlSession中查詢相同的sql語句,第一次查詢后會將結果對象存放在一級緩存中,在后面查詢相同的sql語句的時候會在一級緩存中去獲取,不用在與數據庫進行通信,大大降低了查詢速度.
第2種情況:同個session進行兩次不同的查詢。
** 代碼演示**
//測試一級緩存@Testpublic void testCache() throws IOException {//加載配置文件InputStream rs = Resources.getResourceAsStream("MyBatisConfig.xml");//獲取工廠建造類SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//獲取工廠對象SqlSessionFactory build = sqlSessionFactoryBuilder.build(rs);//獲取SqlSession對象SqlSession sqlSession = build.openSession(true);//得到代理的對象StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);//根據名字查詢Student stu1 = mapper.findStudentByName("小花花");Student stu2 = mapper.findStudentByName("小付");System.out.println("兩次查詢結果的學生對象是否是同一個:"+(stu1==stu2));//關閉會話sqlSession.close();rs.close();}控制臺輸出
第3種情況:不同session,進行相同查詢。
** 代碼演示**
//測試一級緩存@Testpublic void testCache() throws IOException {//加載配置文件InputStream rs = Resources.getResourceAsStream("MyBatisConfig.xml");//獲取工廠建造類SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//獲取工廠對象SqlSessionFactory build = sqlSessionFactoryBuilder.build(rs);//獲取SqlSession對象SqlSession sqlSession = build.openSession(true);StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);//獲取SqlSession2對象SqlSession sqlSession2 = build.openSession(true);StudentMapper mapper2 = sqlSession2.getMapper(StudentMapper.class);//根據名字查詢Student stu1 = mapper.findStudentByName("小花花");Student stu2 = mapper2.findStudentByName("小花花");System.out.println("兩次查詢結果的學生對象是否是同一個:"+(stu1==stu2));//關閉會話sqlSession.close();rs.close();}控制臺輸出
第4種情況:同個session,查詢之后更新數據,再次查詢相同的語句。
代碼演示
//測試一級緩存@Testpublic void testCache() throws IOException {//加載配置文件InputStream rs = Resources.getResourceAsStream("MyBatisConfig.xml");//獲取工廠建造類SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//獲取工廠對象SqlSessionFactory build = sqlSessionFactoryBuilder.build(rs);//獲取SqlSession對象SqlSession sqlSession = build.openSession(true);//得到代理的對象StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);//根據名字查詢Student stu1 = mapper.findStudentByName("小花花");//修改數據stu1.setAge(18);//執行更新語句mapper.updateStudent(stu1);//再次查詢Student stu2 = mapper.findStudentByName("小花花");System.out.println("兩次查詢結果的學生對象是否是同一個:"+(stu1==stu2));//關閉會話sqlSession.close();rs.close();}控制臺輸出
一級緩存結論
MyBatis一級緩存的運行過程是這樣的:執行SQL語句的過程中,首次執行它時從數據庫獲取的所有數據會被存儲在一段高速緩存中,今后執行這條語句時就會從高速緩存中讀取結果,而不是再次查詢數據庫。MyBatis提供了默認下基于Java HashMap的緩存實現。
重點是要明白:MyBatis執行SQL語句之后,這條語句的執行結果被緩存,以后再執行這條語句的時候,會直接從緩存中拿結果,而不是再次執行SQL。但是一旦執行新增或更新或刪除操作,緩存就會被清除。下面將分情況來驗證一下。
很明顯,以上各種情況驗證了一級緩存的概念,在同個SqlSession中,查詢語句相同的sql會被緩存,但是一旦執行新增或更新或刪除操作,緩存就會被清除。
MyBatis的二級緩存(全局緩存)
引入
MyBatis 一級緩存最大的共享范圍就是一個SqlSession內部,那么如果多個 SqlSession 需要共享緩存,則需要開啟二級緩存.
當二級緩存開啟后,同一個命名空間(namespace) 所有的操作語句,都影響著一個共同的 cache,也就是二級緩存被多個 SqlSession 共享,是一個全局的變量。當開啟緩存后,數據的查詢執行的流程就是 二級緩存 -> 一級緩存 -> 數據庫。
二級緩存開啟條件
二級緩存默認是不開啟的,需要手動開啟二級緩存,實現二級緩存的時候,MyBatis要求返回的**POJO必須是可序列化的**。開啟二級緩存的條件也是比較簡單.
在MyBatis核心配置文件中配置開啟二級緩存
<!-- 通知 MyBatis 框架開啟二級緩存 --> <settings><setting name="cacheEnabled" value="true"/> </settings>在mapper配置文件中開啟當前命名空間的查詢結果存放在二級緩存中
<!-- 表示DEPT表查詢結果保存到二級緩存(共享緩存)cache 標簽有多個屬性,一起來看一些這些屬性分別代表什么意義eviction: 緩存回收策略,有這幾種回收策略LRU - 最近最少回收,移除最長時間不被使用的對象FIFO - 先進先出,按照緩存進入的順序來移除它們SOFT - 軟引用,移除基于垃圾回收器狀態和軟引用規則的對象WEAK - 弱引用,更積極的移除基于垃圾收集器和弱引用規則的對象默認是 LRU 最近最少回收策略flushinterval 緩存刷新間隔,緩存多長時間刷新一次,默認不清空,設置一個毫秒值readOnly: 是否只讀;true 只讀,MyBatis 認為所有從緩存中獲取數據的操作都是只讀操作,不會修改數據。MyBatis 為了加快獲取數據,直接就會將數據在緩存中的引用交給用戶。不安全,速度快。讀寫(默認):MyBatis 覺得數據可能會被修改size : 緩存存放多少個元素type: 指定自定義緩存的全類名(實現Cache 接口即可)blocking: 若緩存中找不到對應的key,是否會一直blocking,直到有對應的數據進入緩存。我這里就使用默認的,不去設置參數--><cacheeviction="FIFO"flushInterval="60000"size="512"readOnly="true"/>實體類對象要Serializable序列化
@Data //這個注解是lombok包下的,可以自動幫我們添加getset方法等 public class Student implements Serializable {private Integer sid;private String name;private Integer age; }代碼驗證
//測試一級緩存@Testpublic void testCache() throws IOException {//加載配置文件InputStream rs = Resources.getResourceAsStream("MyBatisConfig.xml");//獲取工廠建造類SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//獲取工廠對象SqlSessionFactory build = sqlSessionFactoryBuilder.build(rs);//獲取SqlSession對象SqlSession sqlSession = build.openSession(true);StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);//根據名字查詢Student stu1 = mapper.findStudentByName("小花花");System.out.println("第一次查出的對象"+stu1);//關閉會話后,會將一級緩存的數據保存在二級緩存中sqlSession.close();//獲取SqlSession2對象SqlSession sqlSession2 = build.openSession(true);StudentMapper mapper2 = sqlSession2.getMapper(StudentMapper.class);//新的會話查詢就會從二級緩存中獲取數據Student stu2 = mapper2.findStudentByName("小花花");System.out.println("第二次查出的對象"+stu1);System.out.println("兩次查詢結果的學生對象是否是同一個:"+(stu1==stu2));//關閉會話sqlSession2.close();rs.close();}控制臺輸出
圖解查詢語句執行流程
總結
以上是生活随笔為你收集整理的浅谈Mybatis的一级缓存和二级缓存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: javascript的内置对象以及BOM
- 下一篇: jQuery的基本语法,选择器,DOM操