preface

C: In the last article, Zha teacher took you to MyBatis SQL mapping file resultMap element to do an introduction, it is probably the first “block” in MyBatis learning, did not cross over the students also do not matter, take your time, do not be impatient, first look at this again. MyBatis SQL mapping file cache element

The cache is the cache, any application is an indispensable part of the performance, if you want to improve the cache, the cache has to come out. MyBatis naturally also not the existence of cache, let’s go to see it.

Cache element

The cache element is the key used to enable MyBatis level 2 cache. The cache in MyBatis is divided into level 1 cache and level 2 cache.

Level 1 cache

Level 1 caching refers to Session caching and is enabled by default.

Level 1 caches have two scope scopes: [2]

  • SESSION(the default)If the same query is executed multiple times in the same SqlSession, all entries except the first entry are cached
  • STATEMENTLevel 1 cache is cleared after each statement in Mapper (not recommended).

Test the SESSION scope of level 1 cache :(just pick two queries)

class TestMyBatis {

    @Test
    void testSelectByList(a) {
        // Get the SqlSession object
        try (SqlSession sqlSession = MyBatisUtils.openSession()) {

            // Get the Mapper interface
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
			
            // Execute different SQL
            List<User> userList1 = userMapper.selectList();
            List<User> userList2 = userMapper.selectByName("J");
        } catch(Exception e) { e.printStackTrace(); }}}Copy the code

It obviously executes two SQL statements and has nothing to do with caching.

Try executing the same SQL query twice.

class TestMyBatis {

    @Test
    void testSelectByList(a) {
        // Get the SqlSession object
        try (SqlSession sqlSession = MyBatisUtils.openSession()) {

            // Get the Mapper interface
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            // Execute the same SQL
            List<User> userList1 = userMapper.selectList();
            List<User> userList2 = userMapper.selectList();
        } catch(Exception e) { e.printStackTrace(); }}}Copy the code

MyBatis only executes the same SQL query once in the same SqlSession, and then directly uses the cache the second time.

The second level cache

Level 2 cache refers to mapper mapping files. The scope of the level-2 cache is the mapper mapping file content under the same namespace, and multiple SQLSessions are shared.

Note: You can globally turn on/off all level 2 caches through cacheEnabled of the Settings element in the core configuration file (the default is true).

<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>
Copy the code

Before testing level 2 caching, we need to enable level 2 caching for the specified SQL mapping file, that is, adding a cache element.

<! Only one cache element can be used for the same SQL mapping file.
<cache/>
Copy the code

Above we only added an empty cache element, but it already uses a number of cache defaults, which look like this: [1]

  • The results of all SELECT statements in the mapping statement file will be cached.
  • All INSERT, UPDATE, and DELETE statements in the mapping statement file flush the cache (even if no transaction is committed at the end).
  • The cache uses the Least Recently Used algorithm (LRU) algorithm to clear unwanted caches.
  • The cache is not flushed regularly (that is, there are no flush intervals).
  • The cache holds 1024 references to lists or objects (whichever is returned by the query method).
  • The cache is treated as a read/write cache, which means that the retrieved object is not shared and can be safely modified by the caller without interfering with potential changes made by other callers or threads.

You can also adjust the level 2 cache by modifying the attributes of the cache element.

<! This more advanced configuration creates a FIFO cache, refreshed every 60 seconds, that can store up to 512 references to result objects or lists, and the returned objects are considered read-only, so modifying them may conflict with callers in different threads. -->
<cache
    eviction="FIFO"
    flushInterval="60000"
    size="512"
    readOnly="true"/>
Copy the code

Eviction stands for cache cleanup policy :(default cleanup policy is LRU)

  • LRULeast Recently used: Remove the object that has not been used for the longest time
  • FIFOFirst-in, first-out: Objects are removed in the order in which they enter the cache
  • SOFTSoft reference: Objects are removed based on garbage collector state and soft reference rules
  • WEAK– Weak references: Objects are removed more aggressively based on garbage collector state and weak reference rules.

FlushInterval specifies the cache flushInterval (the default is not set, that is, there is no flushInterval; the cache is only flushed when a statement is called). The value of the flushInterval property can be set to any positive integer and should be a reasonable amount of time in milliseconds.

Size represents the number of object references that can be cached (the default is 1024). Its attribute value can be set to any positive integer, but be careful about the size of the object to be cached and the memory resources available in the runtime environment.

ReadOnly indicates whether the object in the cache is read-only (the default is false). Its property value can be set to true or false. Read-only caches return the same instance of cached objects to all callers, so they cannot be modified, providing a significant performance boost. A read-write cache returns (through serialization) a copy of the cached object, which is slower, but safer (recommended).


Test it out:

class TestMyBatis {

    @Test
    void testSelectByList(a) {
        try {
            // Get the SqlSession object
            SqlSession sqlSession1 = MyBatisUtils.openSession();
            / / execution
            UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
            List<User> userList1 = userMapper1.selectList();
            SqlSession (); SqlSession ();
            sqlSession1.close();
			
            // Get the SqlSession object
            SqlSession sqlSession2 = MyBatisUtils.openSession();
            / / execution
            UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
            List<User> userList2 = userMapper2.selectList();
            sqlSession2.close();
        } catch(Exception e) { e.printStackTrace(); }}}Copy the code

The readOnly property defaults to false, meaning that a copy of the cache object is returned each time it is serialized, so that the cache can be read and written.

public class User implements Serializable{
    / / a little
}
Copy the code

After the test, the console output is as follows: Cache Hit Ratio indicates the Cache Hit Ratio. After level-2 Cache is enabled, the system calculates the level-2 Cache Hit Ratio every time a query is executed. The first query is also from the cache, but it must not be in the cache, so the hit ratio is 0, and then from DB to the second level cache. The second query was read from level 2 cache, this time with a hit ratio of 1/2=0.5. Of course, if there is a third query, the hit ratio is 1/3=0.66, and so on. [3]

Cache – the ref element

Cache-ref elements come in handy when we want to share the same cache configuration and instance across multiple namespaces, and cache elements take precedence when both are used.

<! -- Namespace: the value of the namespace of an SQL mapping file to be shared with the level 2 cache -->
<cache-ref namespace="com.example.mapper.UserMapper"/>
Copy the code

Check the teacher say: the second level cache is not everything, need according to the actual situation, when the query than increase deletion operation, and the business of the data real-time demand is not high when the second level cache can be used, otherwise increase bowdlerize frequent refresh the second level cache will reduce the performance of the system, and the cache can lead to poor real-time effect.

In addition, MyBatis level 2 cache also has some defects, the use of MyBatis level 2 cache must have a premise: ensure that all add, delete, change and check under the same namespace, otherwise prone to data inconsistency, such as: When there are operations on the same table in two SQL mapping files, the modification of the table by one of the two SQL mapping files only causes the second-level cache clearing of the SQL mapping file, but not the other one.

reference

[1] MyBatis website. XML mapping file [EB/OL]. mybatis.org/mybatis-3/z… . 2020-12-26

[2] Flower good night ape. Mybatis【 interview questions 】 Describe Mybatis cache – brief answer [EB/OL]. blog.csdn.net/qq_23202687… . 2019-12-26

[3] Chen Haoxiang. Do you really understand the Mybatis cache mechanism [EB/OL]. Mp.weixin.qq.com/s/h2x15k71r… . 2018-07-10

Afterword.

The preliminary study of SQL mapping files is finally over. Fortunately, there is a prototype of the previous article, but it also took half a day to sort out and improve it. I hope it can bring a systematic learning scheme to small white users.

Teacher Zha said: For the learning of technology, teacher Zha has always followed the following steps: With a simple demo to let it run first, and then learn it the most commonly used API and configuration can let yourself up, finally, on the basis of proficiency in the spare time reading the source to try to make myself to be able to see clearly its running mechanism, part of the cause of the problem, at the same time, draw lessons from these technology to enhance your own code level.

So in the teacher’s article, the early basic are small white, only interspersed with a very small amount of source research. Of course, such as the small white update, you still like, the late will not regularly dedicated to part of the technology of the source code analysis.