Mybatis supports second-level caching in addition to first-level caching, which is namespace-level.
1. Level 2 cache
1.1 Level 2 Cache Characteristics
- The second level cache is namespace level, which is superior to sqlSession and can share between sqlSessions.
- Level 2 cache global configuration mode is open and can be turned off
- The secondary cache is transactional, and when sqlSession closes or commits a transaction normally, the primary cache in sqlSession is refreshed to the secondary cache.
- When a transaction rolls back, the first level cache in sqlSession does not refresh to the second level cache.
1.2 Open Level 2 Cache
- The easiest way to open the cache is to add tags directly to the sql mapping file.
- Note that entities that need to be cached need to implement serialized interfaces
<cache/>
1.3 Default Behavior of Cache Labels
Use its default configuration. Default caching features:
- The results of all select statements in the mapping statement file will be cached. You can close the cache of select statements by setting useCache=false
- All insert, update, and delete statements in the mapping statement file refresh the cache.
- Caching uses the Least Current Used (LRU) algorithm to clear unnecessary caches.
- The cache does not refresh regularly (that is, there is no refresh interval).
- The cache stores 1024 references to a list or object, regardless of which query method returns.
- Caches are considered read/write caches, which means that the acquired objects are not shared and can be safely modified by the caller without interfering with potential modifications made by other callers or threads.
<cache/>
1.4 cache tag attributes
The cache tag provides four attributes to customize the behavior of the default secondary cache:
- Flush Interval: Sets the refresh interval, that is, the time to empty the cache, in milliseconds. By default, refresh when calling statements
- size: Sets the maximum number of references to cached objects per namespace, defaulting to 1024.
- readOnly: Sets whether the resulting cache is read-only.
- true: Setting read-only will return the reference to the cache, which will be fast. But it is not safe because it can be modified.
- false: Setting up read and write will generate new objects through deserialization, which will be slightly slower
- eviction: Set cache clearance policy, default LRU.
- LRU: Minimum Recent Use: Remove objects that have not been used for the longest time.
- FIFO: First in, first out: Remove objects in the order they enter the cache.
- SOFT: Soft reference: Removing objects based on garbage collector status and soft reference rules.
- WEAK: Weak references: Remove objects more actively based on garbage collector status and weak reference rules.
2. Level 2 cache testing
2.1 Setting up Global Open Level 2 Cache
The global secondary cache is opened by default, or the declaration is displayed to open the global secondary cache.
<settings> <setting name="cacheEnabled" value="true" /> </settings>
2.2 Entities requiring caching implement serialized interfaces
Because caching requires serialized entities, entities must implement serialized interfaces.
public class EmployeePO implements Serializable { private static final long serialVersionUID = -2164461308545729638L; //... }
2.3 Test Cases
- Test Level 2 Cache Effectiveness: When sqlSession is closed, write Level 1 Cache in this sqlSession to Level 2 Cache
- Test Level 2 Cache Effectiveness: When sqlSession commits a transaction, write Level 1 Cache in this sqlSession to Level 2 Cache
- Test Level 2 cache is not valid: If useCache=false is set in the query, Level 2 cache is not valid
- Test Level 2 Cache does not work: When sqlSession rolls back transactions, the cache in sqlSession is not written to Level 2 Cache
public class TestCacheLevel2 { // Test Level 2 Cache Effectiveness: When sqlSession is closed, write Level 1 Cache in this sqlSession to Level 2 Cache @Test public void test_valid1(){ SqlSession sqlSession1 = SqlSessionUtil.openSession(false); SqlSession sqlSession2 = SqlSessionUtil.openSession(false); EmployeeMapper empMapper1 = sqlSession1.getMapper(EmployeeMapper.class); EmployeeMapper empMapper2 = sqlSession2.getMapper(EmployeeMapper.class); System.out.println("Make the first query..."); EmployeePO emp1 = empMapper1.findById(1L); // When sqlSession closes, the first level cache is written to the second level cache. sqlSession1.close(); System.out.println("Make a second inquiry..."); EmployeePO emp2 = empMapper2.findById(1L); Assert.assertNotEquals(emp1, emp2); } // Test Level 2 Cache Effectiveness: When sqlSession commits a transaction, write Level 1 Cache in this sqlSession to Level 2 Cache @Test public void test_valid2(){ SqlSession sqlSession1 = SqlSessionUtil.openSession(false); SqlSession sqlSession2 = SqlSessionUtil.openSession(false); EmployeeMapper empMapper1 = sqlSession1.getMapper(EmployeeMapper.class); EmployeeMapper empMapper2 = sqlSession2.getMapper(EmployeeMapper.class); System.out.println("Make the first query..."); EmployeePO emp1 = empMapper1.findById(1L); // When sqlSession commits a transaction, the data in this sqlSession is written to the cache sqlSession1.commit(); System.out.println("Make a second inquiry..."); EmployeePO emp2 = empMapper2.findById(1L); Assert.assertNotEquals(emp1, emp2); } // Test Level 2 cache is not valid: If useCache=false is set in the query, Level 2 cache is not valid @Test public void test_invalid1(){ SqlSession sqlSession1 = SqlSessionUtil.openSession(false); SqlSession sqlSession2 = SqlSessionUtil.openSession(false); EmployeeMapper empMapper1 = sqlSession1.getMapper(EmployeeMapper.class); EmployeeMapper empMapper2 = sqlSession2.getMapper(EmployeeMapper.class); System.out.println("Make the first query..."); EmployeePO emp1 = empMapper1.findById(1L); // When sqlSession closes, the first level cache is written to the second level cache. sqlSession1.close(); System.out.println("Make a second inquiry..."); EmployeePO emp2 = empMapper2.findById(1L); Assert.assertNotEquals(emp1, emp2); } // Test Level 2 Cache does not work: When sqlSession rolls back transactions, the cache in sqlSession is not written to Level 2 Cache @Test public void test_invalid2(){ SqlSession sqlSession1 = SqlSessionUtil.openSession(true); SqlSession sqlSession2 = SqlSessionUtil.openSession(true); EmployeeMapper empMapper1 = sqlSession1.getMapper(EmployeeMapper.class); EmployeeMapper empMapper2 = sqlSession2.getMapper(EmployeeMapper.class); System.out.println("Make the first query..."); EmployeePO emp1 = empMapper1.findById(1L); // When sqlSession commits a transaction, the data in this sqlSession is written to the cache sqlSession1.rollback(); System.out.println("Make a second inquiry..."); EmployeePO emp2 = empMapper2.findById(1L); Assert.assertNotEquals(emp1, emp2); } }