In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces "summarizing MyBatis cache structure". In daily operation, I believe many people have doubts about summarizing MyBatis cache structure. The editor consulted all kinds of data and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubts about "summarizing MyBatis cache structure". Next, please follow the editor to study!
Second-level cache
Main contents:
The second-tier cache is built on top of the first-level cache, and when a query request is received, MyBatis will first query the second-level cache. If the secondary cache misses, query the primary cache again. Unlike the first-level cache, the second-level cache and specific namespace binding, the first-level cache is bound to SqlSession.
In the case of using SqlSession according to the MyBatis specification, there is no concurrency problem with the first-level cache. This is not the case with secondary caching, which can be shared across multiple namespaces. In this case, there will be concurrency problems, so it needs to be targeted to deal with. In addition to the concurrency problem, there is also a transaction problem in the secondary cache.
How to turn on the second-level cache?
Configuration item
CacheEnabled=true indicates that secondary cache is available, but to enable it, it needs to be configured in Mapper.xml.
Or a simple way.
Description for configuration item properties:
FlushInterval= "60000", which empties the cache at an interval of 60 seconds, is passively triggered rather than polled by a timer.
Size=512, which means the maximum length of the queue is 512. if it is greater than that, the first element of the queue is removed. Here, the length refers to the number of CacheKey. The default is 1024.
ReadOnly= "true", which means that any operation that gets an object will return the same instance object. If readOnly= "false", a copy of the object is returned each time, which is simply a serialized copy of the return.
Eviction: the cache is retrieved using the default Least Recently Used (LRU, the least recently used) algorithm. FIFO:First In First Out FIFO queue.
Whether to enable secondary caching in the newExecutor method of the Configuration class
Public Executor newExecutor (Transaction transaction, ExecutorType executorType) {executorType = executorType = = null? DefaultExecutorType: executorType; executorType = executorType = = null? ExecutorType.SIMPLE: executorType; Executor executor; if (ExecutorType.BATCH = = executorType) {executor = new BatchExecutor (this, transaction);} else if (ExecutorType.REUSE = = executorType) {executor = new ReuseExecutor (this, transaction);} else {executor = new SimpleExecutor (this, transaction);} / / whether to enable secondary cache if (cacheEnabled) {executor = new CachingExecutor (executor) } executor = (Executor) interceptorChain.pluginAll (executor); return executor;}
The second-level cache is implemented through CachingExecutor. The principle is that if it exists in the cache, it will be returned, and if it does not exist, Executor will be called. If the first-level cache is not closed, then check the first-level cache, which does not exist, and then query it in the database.
The following is represented by a picture:
Here is the source code:
@ Overridepublic List query (MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {/ / get BoundSql object BoundSql boundSql = ms.getBoundSql (parameterObject); / / create CacheKey object CacheKey key = createCacheKey (ms, parameterObject, rowBounds, boundSql); / / query return query (ms, parameterObject, rowBounds, resultHandler, key, boundSql) } @ Overridepublic List query (MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {/ / calls the MappedStatement#getCache () method to get the Cache object, which is the secondary cache of the current MappedStatement object. Cache cache = ms.getCache (); if (cache! = null) {/ clear flushCacheIfRequired (ms) if you need to clear the cache; / / use the secondary cache only when the MappedStatement#isUseCache () method returns true. It is on by default. / / can be closed through @ Options (useCache = false) or method. If (ms.isUseCache () & & resultHandler = = null) {/ temporarily ignored, stored procedure related ensureNoOutParams (ms, boundSql); @ SuppressWarnings ("unchecked") / / from the secondary cache, get the result List list = (List) tcm.getObject (cache, key) If (list = = null) {/ / if it does not exist, query list = delegate.query (ms, parameterObject, rowBounds, resultHandler, key, boundSql) from the database; / / cache the result to tcm.putObject (cache, key, list) in the secondary cache / / issue # 578 and # 116} / / if the result is returned directly, return list;}} / / query return delegate.query (ms, parameterObject, rowBounds, resultHandler, key, boundSql) from the database;} how is the secondary cache key generated?
It is also generated using the createCacheKey method in the BaseExecutor class, so the second-level cache key is the same as the first-level cache generation rule.
Second-level cache range
Secondary caching has a very important space allocation strategy:
Namespace= "com.tian.mybatis.mappers.UserMapper" namespace= "com.tian.mybatis.mappers.RoleMapper"
That is, according to the namespace division, the same namespace, the same Cache space, different namespace, different Cache space.
For example:
The secondary cache under this namespace is the same.
When will the secondary cache be cleared?
The secondary cache is cleared whenever insert, update, or delete,flushCache=true are executed.
The transaction is not committed and the secondary cache does not take effect. SqlSession sqlSession = sqlSessionFactory.openSession (); System.out.println ("first query"); User user = sqlSession.selectOne ("com.tian.mybatis.mapper.UserMapper.selectById", 1); System.out.println (user); / / sqlSession.commit (); SqlSession sqlSession1 = sqlSessionFactory.openSession (); System.out.println ("second query"); User user2 = sqlSession1.selectOne ("com.tian.mybatis.mapper.UserMapper.selectById", 1); System.out.println (user2)
Because the secondary cache is managed by TransactionalCaheManager (tcm), the getObject (), putObject (), commit methods of TranscatinalCache are finally called.
TransactionalCache also holds real Cache objects, such as PrepetualCache, which has been decorated layer by layer.
In putObject, it is just added to the entriesToAddOnCommit.
/ / @ Overridepublic void putObject (Object key, Object object) in the TransactionalCache class {/ / temporarily store KV to entriesToAddOnCommit entriesToAddOnCommit.put (key, object);}
Only when the conmit method is called will the flushPendingEntries method be called and actually written to the cache. DefaultSqlSession calls this commit method when it calls the commit method.
/ / public void commit () {/ / if clearOnCommit is true, clear delegate cache if (clearOnCommit) {delegate.clear ();} / / Brush entriesToAddOnCommit and entriesMissedInCache into flushPendingEntries () in delegate; / / reset reset () } private void flushPendingEntries () {/ / Brush entriesToAddOnCommit into delegate for (Map.Entry entry: entriesToAddOnCommit.entrySet ()) {delegate.putObject (entry.getKey (), entry.getValue ());} / / Brush entriesMissedInCache into delegate for (Object entry: entriesMissedInCache) {if (! entriesToAddOnCommit.containsKey (entry)) {delegate.putObject (entry, null) } private void reset () {/ / reset clearOnCommit to false clearOnCommit = false; / / clear entriesToAddOnCommit, entriesMissedInCache entriesToAddOnCommit.clear (); entriesMissedInCache.clear ();} Why does adding or deleting this operation clear the secondary cache?
Because in the update method of CachingExecutor
@ Overridepublic int update (MappedStatement ms, Object parameterObject) throws SQLException {flushCacheIfRequired (ms); return delegate.update (ms, parameterObject);} private void flushCacheIfRequired (MappedStatement ms) {Cache cache = ms.getCache (); / / whether to clear the cache / / through @ Options (flushCache = Options.FlushCachePolicy.TRUE) or method, / / to clear the cache when enabled. If (cache! = null & & ms.isFlushCacheRequired ()) {/ / calls the TransactionalCache#clear () method to clear the cache. / / Note that only the cache generated by the query data in the current transaction is cleared at this time. / / and the actual emptying occurs when the transaction is committed. Why is that? / / also because the secondary cache is shared across Session, no modifications can be made to the secondary cache before the transaction ends. Tcm.clear (cache);}} how to achieve cache sharing among multiple namespace?
The problem of cache sharing for multiple namespace can be solved by using.
For example:
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.