#We know that frequent database operations are very performance-consuming (mainly because for DB, data is persistent is stored in the disk, so the query operation needs to go through IO, and the IO operation speed is several orders of magnitude slower than the memory operation speed), especially for some identical query statements, the query results can be stored, and the next query will be the same When querying the content, you can directly obtain the data from the memory, which can greatly improve query efficiency in certain scenarios.
MyBatis’s cache is divided into two types:
First-level cache, the first-level cache isSqlSession level cache, for the same query, the results will be returned from the cache instead of querying the database
Level 2 cache, The second-level cache is a cache at the Mapper level. It is defined in the tag of the Mapper file and needs to be turned on. Multiple Mapper files can share one cache, depending on Tag configuration
Let’s take a detailed look at the first and second level cache of MyBatis.
MyBatis first-level cache workflow
Then let’s take a look at the MyBatis first-level cache work process. As mentioned earlier, the first-level cache of MyBatis is a SqlSession-level cache. When the openSession() method finishes running or the close method of SqlSession is actively called, the SqlSession is recycled, and the first-level cache is also recycled at the same time. . As mentioned in the previous article, in MyBatis, both the selectOne and selectList methods are eventually converted to the selectList method for execution, so take a look at the implementation of the selectList method of SqlSession:
Line 3 builds the cache condition CacheKey, which involves how the conditions are equal to the above A query is a question of the same condition, because the same condition can return the previous result. This part of the code will be left for analysis in the next part.
Then look at the implementation of the query method in line 4. The code is located in CachingExecutor:
1 public int update(MappedStatement ms, Object parameter) throws SQLException {2 ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());3 if (closed) {4 throw new ExecutorException("Executor was closed.");5 }6 clearLocalCache();7 return doUpdate(ms, parameter);8 }
1 public class CacheKey implements Cloneable, Serializable { 2 3 private static final long serialVersionUID = 1146682552656046210L; 4 5 public static final CacheKey NULL_CACHE_KEY = new NullCacheKey(); 6 7 private static final int DEFAULT_MULTIPLYER = 37; 8 private static final int DEFAULT_HASHCODE = 17; 9 10 private int multiplier;11 private int hashcode;12 private long checksum;13 private int count;14 private List<object> updateList;15 ...16 }</object>
1 public void update(Object object) { 2 if (object != null && object.getClass().isArray()) { 3 int length = Array.getLength(object); 4 for (int i = 0; i
select a.col1, a.col2, a.col3, b.col1, b.col2, b.col3 from tableA a, tableB b where a.id = b.id;
The operations for tableA and tableB are defined in two Mappers, called MapperA and MapperB respectively, that is, they belong to two namespaces. If caching is enabled at this time:
Execute the above sql statement in MapperA to query these 6 fields
tableB updated the two fields col1 and col2
MapperA executes the above sql statement again to query these 6 fields (provided that it is not executed After any insert, delete, update operations)
The problem arises at this time, even if tableB updates col1 in step (2) With the two fields col2 , in step (3), the 6 fields obtained by MapperA through the second-level cache are still the values of the original 6 fields, because we get the values from the CacheKey Look at the three sets of conditions:
## The Namespace of the Mapper where the label is located + the id attribute of the label
The offset and limit attributes of RowBounds. RowBounds is a class used by MyBatis to handle paging. The default offset is 0 and the limit defaults to Integer.MAX_VALUE
The sql statement defined in the tag
##For MapperA, any one of the conditions If there is no change, the original result will naturally be returned.
This problem is an unsolvable problem for MyBatis's second-level cache, so there is a prerequisite for using MyBatis's second-level cache:
Must ensure that all increases Delete, modify and check all in the same namespace..
The above is the detailed content of [MyBatis source code analysis] MyBatis first and second level cache. For more information, please follow other related articles on the PHP Chinese website!
Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn