Caching of MyBatis query results

The caching of mybatis refers to caching query results. When using the same sql statement and passing in the same parameters to query in the future, the query results can be obtained directly from the local caching of mybatis without querying the database.

mybatis's cache includes the first level cache and the second level cache. The first level cache is on by default, and the second level cache is off by default.

 

First level cache:

At SqlSession level, there is a Map in SqlSession. key is the only value composed of sql statements, parameters and other information. Value is the result object queried.

 

L2 cache:

Mapper level, mapper under the same namespace, has a Map.

 

 

 

The second level cache can make these sqlsessions share query results.

 

 

 

 

First level cache

The first level cache is on by default.

 

        User user1 = mapper.queryUserById(1);
        User user2 = mapper.queryUserById(1);

On the first query, the query results are placed in the first level cache.

If the subsequent sql statements are the same and the arguments passed in are the same, the result objects will be the same. The result objects will be obtained directly from the first level cache and the database will not be queried.

 

 

        User user1 = mapper.queryUserById(1);
        sqlSession.commit();
        User user2 = mapper.queryUserById(1);

If the sqlSession calls the commit() method, the first level cache of the sqlSession is automatically cleared.

Because using commit() will submit the modification to the database. The next time the same query is used, the query result may change. The previous level-1 cache cannot be used anymore, so it will be automatically cleared.

 

 

     User user1 = mapper.queryUserById(1);

        HashMap<String, Object> map = new HashMap<>();
        map.put("username", "Zhang San");
        map.put("id", 1);
        mapper.updateUser(map);

        User user2 = mapper.queryUserById(1);

In fact, as long as the sqlSession calls the elements that will modify the database, such as < update >, < Insert >, < delete >, the first level cache of the sqlSession will be emptied, regardless of whether it is committed using commit().

 

 

 

 

Two level cache

     SqlSession sqlSession1 = MyBatisUtils.getSqlSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        User user1 = mapper1.queryUserById(1);
        System.out.println(user1);

        SqlSession sqlSession2 = MyBatisUtils.getSqlSession();
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = mapper2.queryUserById(1);
        System.out.println(user2);

Without L2 cache, the query will be executed twice.

 

 

For the steps of using the secondary cache, take UserMapper as an example:

(1) If the pojo class is serializable

public class User implements Serializable {
    //......
}

 

 

(2) Enable secondary caching in mybatis global configuration file

<settings>
        <setting name="logImpl" value="LOG4J"/>
        <setting name="cacheEnabled" value="true"/>
</settings>

The second level cache is closed by default and needs to be opened manually.

 

 

(3) Specify the implementation of L2 cache in mapper mapping file, which must be explicitly specified

<?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.chy.mapper.UserMapper">
    <cache />
    <select id="queryUserById" parameterType="integer" resultType="user">
        SELECT * FROM user_tb WHERE id=#{id}
     </select>
    <update id="updateUser" parameterType="hashmap">
        UPDATE user_tb SET username=#{username} WHERE id=#{id}
    </update>
</mapper>

 

Complete writing:

<cache type="perpetualCache" />

Type specifies the implementation method of the second level cache. The default type is the personal cache provided by mybatis.

 

 

(4) The sqlSession needs to be closed by calling close() to write the query results (primary cache) of this sqlSession to the secondary cache

     SqlSession sqlSession1 = MyBatisUtils.getSqlSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        User user1 = mapper1.queryUserById(1);
        System.out.println(user1);
        sqlSession1.close();

        SqlSession sqlSession2 = MyBatisUtils.getSqlSession();
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = mapper2.queryUserById(1);
        System.out.println(user2);

Only one query is executed. When using the same sql statement and passing in the same arguments for query, the result object is directly obtained from the secondary cache.

 

 

When a modification is submitted, the entire L2 cache is cleared:

     SqlSession sqlSession1 = MyBatisUtils.getSqlSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        User user1 = mapper1.queryUserById(1);
        System.out.println(user1);

        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("username", "j");
        hashMap.put("id", 1);
        mapper1.updateUser(hashMap);
        sqlSession1.commit();

        SqlSession sqlSession2 = MyBatisUtils.getSqlSession();
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = mapper2.queryUserById(2);
        System.out.println(user2);

 

If only commit() is written and < Insert > | < update > | < delete > is not called, the second level cache will not be emptied, but the previous query results will be written to the second level cache.

If commit() is written and < Insert > | < update > | < delete > is called, the entire L2 cache will be cleared.

After calling commit(), close(), the two level cache will not be written. Because commit() exists, it will empty the entire two level cache.

Keywords: Java Mybatis SQL Database log4j

Added by grandeclectus on Sun, 12 Jan 2020 13:53:13 +0200