[Mybatis from entry to actual combat tutorial] Chapter 7 Detailed Explanation of Mybatis Query Cache

Seven, Mybatis query cache

    Caching: Temporarily store data in storage media (memory, files). The purpose of caching in relational databases is to reduce the pressure on the database.
    
    The data of the database is actually stored in the hard disk. If our program needs to use data, it needs to read data from the disk frequently, which is inefficient and puts a lot of pressure on the database. We can cache the queried data, which reduces the frequent operation of disk data, improves query efficiency, and reduces server pressure.
    
    Mybatis provides query caching to reduce database pressure and improve database performance. However, in actual project development, the caching mechanism of Mybatis is rarely used. Now the mainstream caching mechanism is redis.

7.1 What is query cache

  • MyBatis provides query cache to reduce database pressure and improve database performance;

  • MyBatis provides first-level cache and second-level cache;

  • The first level cache is the cache at the SqlSession level. When operating the database, it is necessary to construct a SqlSession object, and there is a data structure (HashMap) in the object for storing cached data. The cache data area (HashMap) between different SqlSessions does not affect each other;

  • The second-level cache is a mapper-level cache. Multiple SqlSessions operate the SQL statement of the same mapper. Multiple SqlSessions can share the second-level cache, and the second-level cache is across SqlSessions;

7.2 Level 1 cache

7.2.1 Working Principle of Level 1 Cache

  • The first time you query the data with id 1, first go to the first-level cache to find out whether there is data with id 1, if not, query the data from the database and store the data in the first-level cache;

  • The second time to query the data with id 1, first go to the first-level cache to find out whether there is data with id 1, if there is in the cache, get the data directly from the cache, and no longer query the database;

  • If SqlSession performs a commit operation (insert, update, delete), it will clear the first-level cache in SqlSession. The purpose of this is to store the latest data in the cache and avoid dirty reading;

7.2.2 Entity classes

public class Person {

    private Integer id;
    private String personName;
    private Integer personAge;
    private String personAddress;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getPersonName() {
        return personName;
    }

    public void setPersonName(String personName) {
        this.personName = personName;
    }

    public Integer getPersonAge() {
        return personAge;
    }

    public void setPersonAge(Integer personAge) {
        this.personAge = personAge;
    }

    public String getPersonAddress() {
        return personAddress;
    }

    public void setPersonAddress(String personAddress) {
        this.personAddress = personAddress;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", personName='" + personName + '\'' +
                ", personAge=" + personAge +
                ", personAddress='" + personAddress + '\'' +
                '}';
    }
}

7.2.3 mapper interface

public interface PersonMapper {

    Person selectById(Integer id);

    List<Person> select();
}

7.2.4 mapper file

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.newcapec.mapper.PersonMapper">

    <select id="selectById" parameterType="java.lang.Integer" resultType="com.newcapec.entity.Person">
        select id,person_name,person_age,person_address from person where id=#{id}
    </select>

    <select id="select" resultType="com.newcapec.entity.Person">
        select id,person_name,person_age,person_address from person
    </select>
</mapper>

7.2.5 Testing

public class CacheTest {

    @Test
    public void testSqlSessionCache() {
        SqlSession sqlSession = MybatisUtil.getSession();
        PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);

        System.out.println("----------第一次使用id为1的person数据-----------");
        Person p1 = personMapper.selectById(1);
        System.out.println(p1);

        /**
         * 一级缓存自带缓存,不可不用的,缓存介质为内存
         * commit()提交方法可以请求缓存
         */
        //sqlSession.commit();

        System.out.println("----------第二次使用id为1的person数据-----------");
        Person p2 = personMapper.selectById(1);
        System.out.println(p2);

        sqlSession.close();
    }
}

7.3 Second level cache

7.3.1 Working Principle of L2 Cache

  • SqlSession1 to query the data whose id is 1, and store the data in the secondary cache after querying;

  • SqlSession2 to query the data whose id is 1, to find whether there is data in the cache, if there is, directly fetch the data from the cache;

  • If SqlSession3 executes sql under the same mapper, executes commit submission, and clears the data in the secondary cache area under the mapper;

  • The difference between the second-level cache and the first-level cache is that the scope of the second-level cache is larger, and multiple SqlSessions can share a Mapper's second-level cache area;

  • Each mapper has a second-level cache area, divided by namespace;

  • If the namespaces of the two mappers are the same, the two mappers execute SQL queries and the data will be stored in the same secondary cache area;

7.3.2 Enable L2 cache

Configure in the mybatis core configuration file: cacheEnabled

setting items describe allowance Defaults
cacheEnabled Global on/off settings for all caches under this configuration file true \ false true
<!-- 全局参数设置 -->
<settings>
    <!-- 开启二级缓存-->
    <setting name="cacheEnabled" value="true"/>
</settings>

Open the second cache in the mapping file, and the SQL under mapper.xml will be stored in its cache area HashMap after the SQL execution is completed.

<mapper namespace="com.newcapec.mapper.PersonMapper">
    <!-- 配置当前mapper文件中所有查询语句都放入二级缓存中 -->
    <cache/>
    
    <select>
        ...
    </select>
</mapper>

7.3.3 Entity classes

    The entity class that stores data in the second-level cache must implement the serializable interface java.io.Serializable.

public class Person implements Serializable {
    
}

7.3.4 L2 cache test

@Test
public void testMapperCache(){
    /**
     * 二级缓存,可插拔式缓存,缓存介质:内存+磁盘
     */

    SqlSession sqlSession1 = MybatisUtil.getSession();
    PersonMapper personMapper1 = sqlSession1.getMapper(PersonMapper.class);
    System.out.println("-------------第一次查询--------------");
    Person p1 = personMapper1.selectById(2);
    System.out.println(p1);
    sqlSession1.close();

    System.out.println("----------------sqlSession1关闭,建立sqlSession2连接-------------------");

    SqlSession sqlSession2 = MybatisUtil.getSession();
    PersonMapper personMapper2 = sqlSession2.getMapper(PersonMapper.class);
    System.out.println("-------------第二次查询--------------");
    Person p2 = personMapper2.selectById(2);
    System.out.println(p2);
    sqlSession2.close();
}

7.3.5 useCache configuration

    Setting useCache="false" in the statement can disable the second-level cache of the current select statement, that is, each query will send sql to query. The default is true, that is, the SQL uses the second-level cache.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.newcapec.mapper.PersonMapper">

    <!-- 配置当前mapper文件中所有查询语句都放入二级缓存中 -->
    <cache/>

    <select id="selectById" parameterType="java.lang.Integer" resultType="com.newcapec.entity.Person" useCache="true">
        select id,person_name,person_age,person_address from person where id=#{id}
    </select>

    <!-- select标签中的useCache属性: 决定了当前sql是否使用二级缓存,默认为true -->
    <select id="select" resultType="com.newcapec.entity.Person" useCache="false">
        select id,person_name,person_age,person_address from person
    </select>
</mapper>

test:

@Test
public void testMapperCache2() {
    SqlSession sqlSession1 = MybatisUtil.getSession();
    PersonMapper personMapper1 = sqlSession1.getMapper(PersonMapper.class);
    System.out.println("-------------第一次查询--------------");
    List<Person> list1 = personMapper1.select();
    System.out.println(list1);
    sqlSession1.close();

    System.out.println("----------------sqlSession1关闭,建立sqlSession2连接-------------------");

    SqlSession sqlSession2 = MybatisUtil.getSession();
    PersonMapper personMapper2 = sqlSession2.getMapper(PersonMapper.class);
    System.out.println("-------------第二次查询--------------");
    List<Person> list2 = personMapper2.select();
    System.out.println(list2);
    sqlSession2.close();
}

Guess you like

Origin blog.csdn.net/ligonglanyuan/article/details/124419889