[9] Mybatis first level cache [when the first level cache is invalid], the second level cache

14. Cache

14.1 Introduction

1. What is cache [Cache ]?

  • Temporary data stored in memory.
  • Put the data frequently queried by users in the cache (memory), and users do not need to query from the disk (relational database data files) to query the data, and query from the cache, thereby improving query efficiency and solving the performance problem of high concurrent systems .

2. Why use cache?

  • Reduce the number of interactions with the database, reduce system overhead, and improve system efficiency.

3. What kind of data can be cached?

  • Data that is frequently queried and not frequently changed.

14.2, Mybatis cache

  • MyBatis includes a very powerful query cache feature, it can be very convenient to customize and configure the cache. Caching can greatly improve query efficiency.

  • Two levels of cache are defined by default in the MyBatis system: the first level cache and the second level cache

    • By default, only the first level cache is enabled. (SqlSession level cache, also called local cache)
    • The second level cache needs to be manually opened and configured, it is based on the namespace level cache.
    • In order to improve scalability, MyBatis defines a cache interface Cache. We can customize the secondary cache by implementing the Cache interface

14.3, primary buffer

The first level cache is also called the local cache:

  • The data queried during the same session with the database will be placed in the local cache.
  • If you need to get the same data in the future, you can get it directly from the cache without having to query the database again;

test

    @Test
    public void getUserByID(){
    
    
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper.getUserByID(1);
        System.out.println(user1);
        System.out.println("=====================================================");
        User user2 = mapper.getUserByID(1);
        System.out.println(user2);
        System.out.println(user1==user2);
        sqlSession.close();
    }

Insert picture description here

Query the same user based on the same id, there is a first-level cache, and only one SQL query is performed

Four situations of first-level cache failure

  1. sqlSession is different

    @Test
    public void testQueryUserById(){
          
          
       SqlSession session = MybatisUtils.getSession();
       SqlSession session2 = MybatisUtils.getSession();
       UserMapper mapper = session.getMapper(UserMapper.class);
       UserMapper mapper2 = session2.getMapper(UserMapper.class);
    
       User user = mapper.queryUserById(1);
       System.out.println(user);
       User user2 = mapper2.queryUserById(1);
       System.out.println(user2);
       System.out.println(user==user2);
    
       session.close();
       session2.close();
    }
    

    Observation result: Found that two SQL statements were sent!

Insert picture description here

Conclusion: The cache in each sqlSession is independent of each other

  1. Same sqlSession but different query conditions

    @Test
    public void testQueryUserById(){
          
          
       SqlSession session = MybatisUtils.getSession();
       UserMapper mapper = session.getMapper(UserMapper.class);
       UserMapper mapper2 = session.getMapper(UserMapper.class);
    
       User user = mapper.queryUserById(1);
       System.out.println(user);
       User user2 = mapper2.queryUserById(2);
       System.out.println(user2);
       System.out.println(user==user2);
    
       session.close();
    }
    

    Observation result: Found that two SQL statements were sent! Normal understanding

    Insert picture description here

    Conclusion: This data does not exist in the current cache

  2. The sqlSession is the same, the addition, deletion and modification operations are performed between the two queries!

        @Test
        public void updateUser(){
          
          
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user1 = mapper.getUserByID(1);
            System.out.println(user1);
    
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("pwd","555555");
            map.put("id",8);
            int i = mapper.updateUser(map);
            System.out.println(i);
    
            User user2 = mapper.getUserByID(1);
            System.out.println(user2);
            System.out.println(user1==user2);
            sqlSession.close();
        }
    

    Observation result: After the query is added, deleted and modified in the middle, re-execute the query sql statement

    Insert picture description here

    Conclusion: Because the addition, deletion, and modification operations may affect the current data

  3. Same as sqlSession, manually clear the first level cache

        @Test
        public void getUserByID(){
          
          
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user1 = mapper.getUserByID(1);
            System.out.println(user1);
            System.out.println("=====================================================");
            sqlSession.clearCache();
            User user2 = mapper.getUserByID(1);
            System.out.println(user2);
            System.out.println(user1==user2);
            sqlSession.close();
        }
    

    Insert picture description here

14.4, secondary cache

  • The second-level cache is also called the global cache, the scope of the first-level cache is too low, so the second-level cache was born

  • Cache based on the namespace level, a namespace corresponds to a secondary cache;

  • Working Mechanism

    • A session queries a piece of data, this data will be placed in the current session's first-level cache;
    • If the current session is closed, the first-level cache corresponding to this session is gone; but what we want is that the session is closed, and the data in the first-level cache is saved to the second-level cache;
    • The new session query information can get the content from the secondary cache;
    • The data detected by different mappers will be placed in their corresponding cache (map);

Steps for usage

  1. Turn on the global cache in the core configuration file mybatis-config

    <setting name="cacheEnabled" value="true"/>
    
  2. Configure the secondary cache in the Mapper.xml mapping file

    <cache/>
    <select id="getUserByID" parameterType="int" resultType="User" useCache="true">
        select * from users where uid = #{id}
    </select>
    

    In the official document:

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

    This more advanced configuration creates a FIFO buffer that is refreshed every 60 seconds. It can store up to 512 references to the result object or list, and the returned objects are considered read-only, so modifying them may occur in different threads. The caller in conflicts.

  3. Code test

    @Test
    public void SecondCache(){
          
          
        SqlSession sqlSession1 = MybatisUtils.getSqlSession();
        SqlSession sqlSession2 = MybatisUtils.getSqlSession();
    
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        User user1 = mapper1.getUserByID(1);
        System.out.println(user1);
        sqlSession1.close();
        System.out.println("==========================================================");
        User user2 = mapper2.getUserByID(1);
        System.out.println(user2);
        sqlSession2.close();
    }
    

    Take a look at the effect:

    Insert picture description here

    As you can see, after the first session is closed, the first level cache is placed in the second level cache, and the second session queries the same data directly from the second level cache

summary

  • As long as the secondary cache is turned on, it will take effect under the same Mapper
  • All data will be placed in the first level cache
  • Only when the session is submitted or closed will it be submitted to the secondary cache

14.5, cache schematic

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_43215322/article/details/109565382