MyBatis一级缓存,二级缓存的实现

本文章介绍实现:

一级缓存:

是指SqlSession。一级缓存的做用域是一个SqlSessionMybatis默认开启一级缓存java

在同一个SqlSession中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;第二次直接从缓存中取。当执行SQL时两次查询中间发生了增删改操做,则SqlSession的缓存清空。mysql


二级缓存:

是指mapper映射文件。二级缓存的做用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis须要手动设置启动二级缓存sql

在同一个namespace下的mapper文件中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;第二次直接从缓存中取。当执行SQL时两次查询中间发生了增删改操做,则二级缓存清空。数据库


 

一.一级缓存的生命周期:

1.MyBatis开启一个会话时,建立SqlSession对象,Excutor对象,PerpetualCache对象。apache

2.会话结束时或SqlSession调用close()方法,释放建立的3个对象。缓存

3.SqlSession调用clearCache()方法否,会清空所有一级缓存当对象仍然存在,可重复使用。session

4.SqlSession执行修改删除添加操做时,会清空PerpetualCache对象。mybatis

 


 

二.二级缓存的过时时间:

1.二级缓存有过时时间,并非key-value的过时时间,而是这个cache的过时时间,是flushInterval,意味着整个清空缓存cache,因此不须要后台线程去定时检测。app

2.每当存取数据的时候,都有检测一下cache的生命时间,默认是1小时,若是这个cache存活了一个小时,那么将整个清空一下。工具

注意:

因为二级缓存的数据不必定都是存储到内存中,它的存储介质多种多样,因此须要给缓存的对象执行序列化。

若是该类存在父类,那么父类也要实现序列化。


 

一级缓存实现:

搭建MyBatis环境:

1.db.properties

1 jdbc.driver=com.mysql.jdbc.Driver
2 jdbc.url=jdbc:mysql://localhost:3306/(数据库)
3 jdbc.username=root
4 jdbc.password=123456

 

2.mybatis-config.xml

 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     <properties resource="db.properties"/>
 8     <settings>
 9         <!--打印执行过程,因为一级缓存是自动开启的,不须要手动开启-->
10         <setting name="logImpl" value="STDOUT_LOGGING"/>
11     </settings>
12     <!--给ccom.Charon.enty包下全部的实体类指定别名-->
13     <typeAliases>
14         <package name="com.Charon.enty"/>
15     </typeAliases>
16 
17     <!-- 数据库链接环境的配置 -->
18     <environments default="development">
19         <environment id="development">
20             <!-- 事务管理器JDBC -->
21             <transactionManager type="JDBC" />
22             <!-- 数据源-->
23             <dataSource type="POOLED">
24                 <property name="driver" value="${jdbc.driver}"/>
25                 <property name="url" value="${jdbc.url}" />
26                 <property name="username" value="${jdbc.username}" />
27                 <property name="password" value="${jdbc.password}" />
28             </dataSource>
29         </environment>
30     </environments>
31     <mappers>
32         <!--必须全包名,否则找不到-->
33         <mapper resource="com/Charon/dao/userMapper.xml"></mapper>
34     </mappers>
35 </configuration>

 

3.userMapper.xml

 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.Charon.dao.UserMapper">
 6     <select id="findUserAll" resultType="user">
 7         SELECT
 8         id id,
 9         username username,
10         userpwd userpassword
11         FROM
12         user
13     </select>
14 </mapper>

 

4.接口UserMapper

 1 package com.Charon.dao;
 2 
 3 import com.Charon.enty.User;
 4 
 5 import java.util.List;
 6 
 7 /**
 8  * @Description TODO
 9  * @Author Charon <1819248612@qq.com>
10  * @create 2020-10-27-21:44
11  * @Version 1.0.0
12  */
13 public interface UserMapper {
14     //查询数据库用户信息
15     List<User> findUserAll();
16 }

 

5.实体类User

**
 * @Description TODO 用户实体类
 * @Author Charon <1819248612@qq.com>
 * @create 2020-10-27-21:37
 * @Version 1.0.0
 */
public class User {
    private Integer id;
    private String username;
    private String userpassword;
    
    //getter ,serter方法省略        
}

 

6.工具类

 1 package com.Charon.utile;
 2 
 3 import org.apache.ibatis.io.Resources;
 4 import org.apache.ibatis.session.SqlSession;
 5 import org.apache.ibatis.session.SqlSessionFactory;
 6 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 7 
 8 import java.io.IOException;
 9 import java.io.InputStream;
10 import java.io.Reader;
11 
12 /**
13  * @Description TODO  代理工厂类
14  * @Author Charon <1819248612@qq.com>
15  * @create 2020-10-21-8:59
16  * @Version 1.0.0
17  */
18 public class MyBatisUtil {
19 
20     private final  static SqlSessionFactory sqlSessionFactory;
21 
22     static {
23         String resource="mybatis-config.xml";
24         Reader reader =null;
25         try {
26             reader = Resources.getResourceAsReader(resource);
27         } catch (IOException e) {
28             e.printStackTrace();
29         }
30         sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
31     }
32 
33     /**
34      * 获取SqlSessionFactory
35      * @return SqlSessionFactory
36      */
37     public static SqlSessionFactory getSqlSessionFactory(){
38         return sqlSessionFactory;
39     }
40 
41     /**
42      * 获取SqlSession
43      * @return SqlSession
44      */
45     public static SqlSession getSqlSession(){
46         return sqlSessionFactory.openSession();
47     }
48 
49     /**
50      * 关闭SqlSession
51      */
52     public  static void closeSession(SqlSession sqlSession){
53         if (sqlSession!=null)
54             sqlSession.close();
55     }
56 }

 

7.测试,这里调用了两次查询

 @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
       //第一次查询
        List<User> userAll = mapper.findUserAll();
        for (int i = 0; i < userAll.size(); i++) {
            User user = userAll.get(i);
            System.out.println(user);
        }
       // 第二次查询
        List<User> userAlls = mapper.findUserAll();
        for (int i = 0; i < userAlls.size(); i++) {
            User user = userAlls.get(i);
            System.out.println(user);
        }
    }

 

8.结果,经过运行结果能够看出当前程序只调用了一次sql

 

 9.屏蔽一级缓存

在userMapper.xml查询添加一个条件

flushCache=true

 

 

 10.屏蔽一级缓存后,展现效果

 


 

二级缓存实现

1.在mybatis-config.xml中设置

 

2.接口UserMapper

 1 package com.Charon.dao;
 2 
 3 import com.Charon.enty.User;
 4 
 5 import java.util.List;
 6 
 7 /**
 8  * @Description TODO
 9  * @Author Charon <1819248612@qq.com>
10  * @create 2020-10-27-21:44
11  * @Version 1.0.0
12  */
13 public interface UserMapper {
14     //查询数据库用户信息
15     List<User> findUserAll();
16 
17     void updateUser(User user);
18 }

 

4.userMapper.xml

 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.Charon.dao.UserMapper">
 6     <!--flushCache=true:屏蔽一级缓存-->
 7     <select id="findUserAll" resultType="user">
 8         SELECT
 9         id id,
10         username username,
11         userpwd userpassword
12         FROM
13         user
14     </select>
15     <update id="updateUser" parameterType="user"  flushCache="true">
16         UPDATE user SET username=#{username},userpwd=#{userpassword} WHERE id=#{id}
17     </update>
18     <!--开启本mapper的namespance下的二级缓存(默认的)-->
19     <cache></cache>
20 </mapper>

 

5.实体类实现Serializable接口

package com.Charon.enty;

import java.io.Serializable;

/**
 * @Description TODO 用户实体类
 * @Author Charon <1819248612@qq.com>
 * @create 2020-10-27-21:37
 * @Version 1.0.0
 */
public class User implements Serializable{
    private Integer id;
    private String username;
    private String userpassword;

    //忽略getter setter方法
}

 

6.测试

 

 7.先把sqlSession注释掉,查看一下二级缓存

 

 8.解注SqlSession3查看二级缓存

 


 

其余配置(useCache和flushCache):

1.MyBatis还能够配置userCache和flushCache等配置项。

2.useCache是用来设置是否禁用二级缓存的,在userMapper.xml中设置useCache=false能够禁用当前select语句的二级缓存

,即每次查询都会发出sql去查询,默认状况是true,即该sql使用二级缓存。

使用演示

<select id="findUserAll" resultType="user" useCache="false">

 

 

3.flushCache:

这种状况是针对每次查询都须要最新的数据sql,要设置成useCache=false,禁用二级缓存,直接从数据库中获取。
在mapper的同一个namespace中,若是有其它insert、update、delete操做数据后须要刷新缓存,若是不执行刷新缓存会出现脏读。

设置statement配置中的flushCache=”true” 属性,默认状况下为true,

即刷新缓存,若是改为false则不会刷新。使用缓存时若是手动修改数据库表中的查询数据会出现脏读。

<update id="updateUser" parameterType="user"  flushCache="true">

 

通常下执行完commit操做都须要刷新缓存,flushCache=true表示刷新缓存,这样能够避免数据库脏读。因此咱们不用设置,默认便可