Mybatis first and second level cache processing
Knowledge:
Level 1 Cache usage scenario
Level 2 Cache usage scenario
1. Level-1 cache application scenario
There is a one-to-many relationship between order table and membership table. In order to reduce join query as much as possible, the query is carried out in stages, that is, the order table is queried first, the membership table is queried according to member_id field, and finally the data is integrated. If there is a duplicate member_id in the order table, there will be a lot of unnecessary duplicate queries. In view of this situation, myBatis is realized by 1 cache. If the same statement and parameter appear in the same query session, it will be removed from the cache and not go to the database query. Level 1 caching is also called session caching because it only works on query sessions.
1.1 Level-1 Cache Example:
LabelMapper mapper = session.getMapper(LabelMapper.class);
Label label = mapper.getById(23);
Label label2 = mapper.getById(23);
Label label3 = sqlSessionFactory.openSession().getMapper(LabelMapper.class).getById(23);
Label label4 = session.getMapper(Label2Mapper.class).getById(23);
System.out.println(label == label2);
System.out.println(label3 == label2);
System.out.println(label4 == label2);
Copy the code
1.2 Application conditions of level 1 Cache
- Must be the same SQL and parameters
- It must be the same session
- The namespace must be the same as the mapper
- They must be the same statement, that is, the same method in the same Mapper interface
- The session.clearCache() method is not executed in the query statement
- No insert UPDATE delete method performed in the middle of the query statement (whether the change record is related to the cached data or not)
1.3 Level 1 cache source code parsing
Cache fetch:
> > mapper. FindById (1) the dao method org. Apache. Ibatis. Session. Defaults. DefaultSqlSession#selectList()
>org.apache.ibatis.executor.CachingExecutor#query()
>org.apache.ibatis.executor.BaseExecutor#query() 142L
>org.apache.ibatis.cache.impl.PerpetualCache#getObject 55L
Copy the code
Cache storage:
> > mapper. FindById (1) the dao method org. Apache. Ibatis. Session. Defaults. DefaultSqlSession#selectList()
>org.apache.ibatis.executor.CachingExecutor#query()
>org.apache.ibatis.executor.BaseExecutor#query() 142L
>org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
>org.apache.ibatis.cache.impl.PerpetualCache#putObject
Copy the code
It is possible to trace the implementation of level 1 cache PerpetualCache by using clearCache as an entry point
>org.apache.ibatis.session.defaults.DefaultSqlSession#clearCache
>org.apache.ibatis.executor.CachingExecutor#clearLocalCache
>org.apache.ibatis.executor.BaseExecutor#clearLocalCache
>org.apache.ibatis.cache.impl.PerpetualCache#clear
Copy the code
Q: Does level 1 caching take effect when another session concurrently modifies the query data? If it does, will it result in incorrect data?
2. Application scenario of level-2 cache
There are a lot of static data in the service system, such as dictionary table, menu table, permission table, etc. The characteristics of these data are hot data that cannot be easily modified but are also queried. Level 1 caching is for the same SQL in the same session and is not suitable for caching hot data. A second level cache was introduced to solve this problem, which is detached from the session.
2.1 Level-2 Cache Example:
@CacheNamespace()
public interface LabelMapper {
@Select("select * from t_label where id =#{id}")
Label getById(Integer id);
}
Copy the code
Attribute Description:
@CacheNamespace( implementation = PerpetualCache.class, // Cache interface implementation class eviction = LruCache. Class,// Cache algorithm flushInterval = 60000, // Max Cache reference object size = 1024, // Max Cache reference objectreadWrite = true, // Can I write blocking =false// Whether to block)Copy the code
2.2 Application Conditions of Level-2 Cache
- The second level cache is populated only after the session is committed or closed
- Must be under the same namespace
- They must be the same statement, that is, the same method in the same Mapper interface
- Must be the same SQL statement and parameters
- If readWrite=true, the entity object must implement the Serializable interface
2.3 Conditions for clearing level-2 Cache
- Update configured in XML cannot clear cached data in @cachenamespace
- The cleanup operation is performed only after the session commit is modified
- Any add, delete, or change operation will clear the cache in the entire namespace
2.4 Source code parsing of level 2 Cache
Clear the cache
>org.apache.ibatis.session.defaults.DefaultSqlSession#selectList() 147L
>org.apache.ibatis.executor.CachingExecutor#query()81L
>org.apache.ibatis.executor.CachingExecutor#query()95L
>org.apache.ibatis.executor.CachingExecutor#flushCacheIfRequired() 164L
Copy the code
Caching caches critical source code
>org.apache.ibatis.cache.TransactionalCacheManager#getObject
>org.apache.ibatis.cache.decorators.TransactionalCache#getObject
>org.apache.ibatis.cache.decorators.SynchronizedCache#getObject
>org.apache.ibatis.cache.decorators.LoggingCache#getObject
>org.apache.ibatis.cache.decorators.SerializedCache#getObject
>org.apache.ibatis.cache.decorators.ScheduledCache#getObject
>org.apache.ibatis.cache.decorators.LruCache#getObject
>org.apache.ibatis.cache.impl.PerpetualCache#getObject
Copy the code
Save level 2 cache
org.apache.ibatis.executor.CachingExecutor#close
>org.apache.ibatis.cache.TransactionalCacheManager#commit
>org.apache.ibatis.cache.decorators.TransactionalCache#flushPendingEntries
>org.apache.ibatis.cache.decorators.SynchronizedCache#putObject
>org.apache.ibatis.cache.decorators.LoggingCache#putObject
>org.apache.ibatis.cache.decorators.SerializedCache#putObject
>org.apache.ibatis.cache.decorators.ScheduledCache#putObject
>org.apache.ibatis.cache.decorators.LruCache#putObject
>org.apache.ibatis.cache.impl.PerpetualCache#putObject
Copy the code
Mybatis dynamic SQL
Basic Command Usage
if
choose (when, otherwise)
trim (where.set)
foreach
Copy the code
Example description:
<trim prefix="where" prefixOverrides="and|or">
<if test="id ! = null">
and id = #{id}
</if>
<if test="name ! = null">
and name = #{name}
</if>
</trim>
Copy the code
1. Trim Attribute Description:
The prefix = "where" / / prefix prefixOverrides = "and | or" / / prefix to replace the word suffix = "" / / add a suffix suffixOverrides =" "/ / suffix to replace the wordCopy the code
2. Element Description:
Before the where the parcel of SQL will automatically add the where characters And get rid of the fore and aft measure and | or characters Under the equivalent configuration:
<trim prefix="where" prefixOverrides="and|or" suffixOverrides="and|or">
Copy the code
3. Element Description:
Before the SQL package set will automatically add set character and remove the beginning and end of the stack, characters.
4. Element Description:
If multiple SQL fragments exist in the same Mapper statement, you can use element declaration and reference elements.
Statement SQL section
<sql id="files">
id ,name ,createTime
</sql>
Copy the code
reference
<include refid="files" />
Copy the code
5. Use of variables
Sometimes you need to do some extra logic by declaring the element and adding the calculation script to its value attribute. The following example automatically adds a % semicolon to likeName. Then you can use #{likeName} to use the % semicolon like operation.
<bind name="likeName" value="'%'+ _parameter.getName() +'%'"></bind>
Copy the code
6. Built-in variables
_databaseID ID of the database _parameter Variation of the current parameter
7. Customize the template interpreter
MyBatis XMLLanguageDriver is the XMLLanguageDriver of myBatis. We can also use an external interpreter such as MyBatis-Velocity or MyBatis- Freemarker to write dynamic scripts.
Mybatis – freemarker use
Introduce mybatis package:
<dependency> <groupId>org.mybatis.scripting</groupId> <artifactId>mybatis-freemarker</artifactId> The < version > 1.1.2 < / version > < / dependency >Copy the code
Adding SQL statements
<select id="selectByIds"
resultType="com.tuling.mybatis.dao.User"
lang="org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver">
select * from user
where id in(${ids? join(',')})
</select>
Copy the code
Adding an interface
List<User> selectByIds(@Param("ids") List<Integer> ids);
Copy the code