Mybatis cache configuration

Preface

Using cache can improve the speed of data acquisition and avoid frequent database interaction, especially in the case of more queries and higher cache hit rate, the role of using cache is more obvious. Generally speaking, when Mybatis cache is mentioned, it refers to the second level cache, which is enabled by default.

First level cache

1. Write a basic mapper to create the sqlsession. The class name is BaseMapperTest

public class BaseMapperTest{
    private static SqlSessionFactory sqlSessionFactory;

    @BeforeClass
    public static void init(){
        try{
            Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            reader.close();
        }catch (IOException ignore){
            ignore.printStackTrace();
        }
    }
 
    public SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

2. Create a cached test class, CacheTest

public class CacheTest extends BaseMapperTest {
    @Test
    public void testL1Cache(){
        //Get SqlSession
        SqlSession sqlSession = getSqlSession();
        SysUser user1 = null;
        try {
            //Get UserMapper interface
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            //Call the selectById method
            user1 = userMapper.selectById(1L);
            //Reassign the currently acquired object
            user1.setUserName("New Name");
            //Query again to get users with the same id
            SysUser user2 = userMapper.selectById(1L);
            //Although the database is not updated, user1 and user2 have the same name
            Assert.assertEquals("New Name",user2.getUserName());
            //In any case, user1 and user2 are the same instance
            Assert.assertEquals(user1,user2);
        }finally {
            sqlSession.close();
        }
        System.out.println("Opening new SqlSession");
        //Open a new sqlsession
        sqlSession = getSqlSession();
        try {
            //Get UserMapper interface
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            SysUser user2 = userMapper.selectById(1L);
            Assert.assertNotEquals("New Name",user2.getUserName());
            //The result of user2 and the previous session query here are two different instances
            Assert.assertNotEquals(user1,user2);
            //Perform delete operation
            userMapper.deleteById(2L);
            //Get user3
            SysUser user3 = userMapper.selectById(1L);
            //user2 and user3 here are two different instances
            Assert.assertNotEquals(user2,user3);
        }finally {
            sqlSession.close();
        }
    }
}

The running results are as follows: in the first try statement block, we wrote the statement to query the database twice, but only one sql was printed out, which proves that the second one does not query the database, but queries the cache, and user1 and user2 are the same instance. First, get the value of user1 from the database, and user1 re assigns the value of userName, The second query found that user2's userName is the modified value of user1.

The first level of Mybatis cache exists in the life cycle of SqlSession. When querying in the same SqlSession, Mybatis will generate the key value of the cache through the algorithm for the executed methods and parameters, and put the key value and the query result into a Map. If the executed methods and parameters in the same SqlSession are exactly the same, the same key value will be generated through the algorithm. When the Map cache object has When the key exists, the object in the cache is returned

What if you don't want to use cache? You can add a flushCache="true" configuration to Mapper's method, which will clear the cache before executing the query.

 <select id="selectById" flushCache="true" resultMap="userMap">
        SELECT * FROM sys_user WHERE id=#{id}
 </select>

In the second try statement block, we get a new sqlsession again. The query result shows that user2 has nothing to do with user1 in the first statement block. When we delete, we use the same sqlsession to perform the same query, and the result is assigned to user3. The result shows that user2 and user3 are different instances, because all inserts, updates, The delete operation will clear the first level cache.

Two level cache

The second level cache of Mybatis is different from the first level cache. The first level cache exists in the life cycle of sqlsession, while the second level cache can be understood as existing in the life cycle of sqlsessionFactory.

1. Simple configuration of mybatis configuration file

In the global configuration settings of Mybatis, there is a parameter cacheEnabled, which is the global switch of the secondary cache. It is true by default, so it can not be configured. If it is set to false, then the configuration of all the caches behind will not work.

   


2. Configure the secondary cache in mapper.xml

Add a cache label to mapper.

3. Related entity class bean objects need to implement serial number interface Serializable

The effect of the default L2 cache:

1. All Select statements will be cached

2. All insert, update and delete operations in the mapping statement will refresh the cache

3. The cache will use LRU algorithm to recycle

The available recovery strategies are LRU:

LRU - least recently used: removes objects that have not been used for the longest time.

FIFO - first in, first out: removes objects in the order they enter the cache.

SOFT – SOFT reference: removes objects based on garbage collector state and SOFT reference rules.

WEAK - WEAK reference: remove objects based on garbage collector state and WEAK reference rules more actively.

4. The cache will store 1024 references of the collection or object

5. Cache will be considered read/write

It can be modified by the following properties:

<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>


3. Configure L2 cache in mapper interface

Add the @ CacheNamespace attribute to the interface. If the interface and XML are configured with caching at the same time, you need to use reference caching, otherwise an error will be reported. Write @ CacheNamespaceRef(XXXMapper.Class) on the interface

 

summary

The first level cache is the default cache used by mybatis, which does not need to be configured manually. The second level cache needs to be configured manually

First level cache failure condition:

1) different sqlsessions, because the first level cache is based on the sqlSession level, the cache is different when different sqlsessions are used for query;
2) the sqlsession is the same, and the first level cache is cleared manually;
3) the sqlsession is the same, and the operation of adding, deleting and modifying is performed between the two queries;
4) the same sqlsession and different query conditions;

By default, the cache provided by Mybatis is a map based memory cache, which can meet the basic use. When the data volume is large, you can use some cache frameworks or Redis cache to help save the secondary cache data of Mybatis.

    

 

Integrated Redis cache

Step 1: add project dependencies

<dependency>
   <groupId>org.mybatis.caches</groudId>
   <artifactId>mybatis-redis</artifactId>
   <version>1.0.0-beta2</version>
</dependency>


Step 2: configure the redis parameter: redis.properties

host=localhost
port=6379
connectionTimeout=5000
soTimeout=5000
password=
database=0
clientName=

Step 3: set the cache type in Mybatis configuration file

<mapper namespace="com.test.MybatisMappings.UserMapper.xml" >
  <cache type="org.mybatis.caches.redis.RedisCache"/>
</mapper>

Tags: Programming Mybatis Database Redis xml

Posted on Sat, 14 Mar 2020 04:57:06 -0700 by z1haze