Mybatis level 1 and level 2 cache, and mybatis Level 2 Cache

Source: Internet
Author: User

Mybatis level 1 and level 2 cache, and mybatis Level 2 Cache
Level 1 Cache

First, perform a test to create a mapper configuration file and mapper interface. Here I use the simplest query for demonstration.

<mapper namespace="cn.elinzhou.mybatisTest.mapper.UserMapper">    <select id="findUsers" resultType="cn.elinzhou.mybatisTest.pojo.User">        SELECT * FROM user    </select></mapper>
public interface UserMapper {    List<User> findUsers()throws Exception;}

Then write a unit test

Public class UserMapperTest {SqlSession sqlSession = null; @ Before public void setUp () throws Exception {// obtain the database connection information through the configuration file Reader = Resources. getResourceAsReader ("cn/elinzhou/mybatisTest/config/mybatis. xml "); // construct a SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder () through configuration information (). build (reader); // use sqlSessionFactory to open a database session sqlSession = sqlSessionFactory. openSession () ;}@ Test public void testFindUsers () throws Exception {UserMapper userMapper = sqlSession. getMapper (UserMapper. class); List <User> users = userMapper. findUsers (); System. out. println (users );}}

Run, you can see that the console output (with log4j first) is similar to the log

The log shows the content that has been queried by the SQL statement executed by this operation. The last line is the result that I manually output through System. out. printf.

Then add a statement.

users = userMapper.findUsers();

The previous unit tests look like this.

That is, after userMapper is executed. findUsers (); then execute userMapper again. findUsers (); as you can imagine, the SQL statements executed by these two operations are exactly the same, and no other operations were performed on the database during this period. Then execute the unit test, and find that the effect is exactly the same as when the above line is executed, that is, the second userMapper is executed. findUsers (); when the database is not queried, where does the obtained data come from? The answer is Level 1 cache.

The mybatis level-1 cache refers to opening up a region in the memory to save the user's database operation information (SQL) and the data returned by the database. If the user executes the same request again next time, reading data directly from the memory instead of from the database.
The data lifecycle has two influencing factors.

Executing the commit operation on sqlsession means that the user has performed the update and delete operations, and the data in the database is bound to change. If the user request data still uses the data in the memory, the dirty data will be read. Therefore, after executing the sqlsession operation, the HashMap storing data will be cleared. When a user initiates a query request, the user will re-read the data and put it in the first-level cache.

In the above test, the commit operation is executed after the first query, and then the query is performed. Different from the previous test, the test console prints two groups of query results, indicating that mybatis re-queries the data after commit.

Generally, when mybatis integrates spring, SqlSessionFactory is set as a singleton and injected into the IOC container. The reason that sqlsession is not set as a singleton is that sqlsession is thread unsafe, therefore, it cannot be a singleton. That means there is actually a process of closing the sqlsession. In fact, the sqlsession in each service is different. This is automatically injected into the service by creating a sqlsession through org. mybatis. spring. mapper. MapperScannerConfigurer in mybatis-spring.
The primary cache is designed to use a separate cache space for each sqlsession. Different sqlsessions cannot access data from each other. Of course, after the sqlsession is disabled, the data is naturally cleared.

Level 2 Cache

Before using the second-level cache, first test the previously mentioned problem that disabling sqlsession will clear the cache and modify the junit code.

@ Test public void testFindUsers () throws Exception {UserMapper userMapper = sqlSession. getMapper (UserMapper. class); List <User> users = userMapper. findUsers (); // close sqlsession sqlSession. close (); // use sqlsessionFactroy to create a new sqlsession sqlSession = sqlSessionFactory. openSession (); // obtain the mapper object userMapper = sqlSession. getMapper (UserMapper. class); users = userMapper. findUsers (); System. out. println (users );}

This code closes the sqlsession after the first query, and creates a new sqlsession and mapper to re-execute the query operation. You can foresee the execution result.

This means that after the sqlsession is closed, the previous cache data is indeed cleared, and the same query operation will be performed to access the database again. To solve this problem, you need to use the second-level cache

The scope of level-1 cache is limited to one sqlsession, but the scope of level-2 cache is a namespace. However, this does not mean that the mapper created in the same namespace can read the cached content from each other,The principle here is that if the second-level cache is enabled, the data in the first-level cache of the sqlsession will be added to the second-level cache of namespace after the sqlsession is disabled.

For the next test, you must first enable the second-level cache.

1. Enable the second-level cache master switch
To enable the master switch, you only need to add a row of settings to the mybatis configuration file.

<Settings> <! -- Enable Level 2 Cache --> <setting name = "cacheEnabled" value = "true"/> </settings>

2. Enable mapper that requires second-level cache

Add the caceh tag to mapper. xml that needs to enable the level-2 cache.

<cache/>

3. POJO serialization

Enable the Serializable interface using the POJO class of the second-level cache, as shown in figure

public class User implements Serializable {

The second-level cache can be used through the previous three steps. Next, we will test it. Add a Junit Method

@ Test public void testFindUsersCache () throws Exception {UserMapper userMapper = sqlSession. getMapper (UserMapper. class); List <User> users = userMapper. findUsers (); // close sqlsession sqlSession. close (); // use sqlsessionFactroy to create a new sqlsession sqlSession = sqlSessionFactory. openSession (); // obtain the mapper object userMapper = sqlSession. getMapper (UserMapper. class); users = userMapper. findUsers (); System. out. println (users );}

After execution, you can find that the console value outputs a query process, or the second-level cache is successfully enabled.

There is another problem. As mentioned earlier, even if the second-level cache is enabled, the cache data between different sqlsessions does not want to access each other. After the sqlsession is closed, to write the data in its first-level cache to the second-level cache. To test this

sqlSession.close();

Note, then the previous Code becomes

After the query is executed, it is found that the query process is too many times output, so it can be confirmed that,Only when sqlsession is disabled will the first-level cache data be written to the second-level cache.

Cache Configuration
  • Disable refresh

By default, the cache will be refreshed after sqlsession executes commit, but it can also be forcibly set to not refresh. Add it to the labels that do not need to be refreshed

flushCache="false" 

For example

<select id="findUsers" resultType="cn.elinzhou.mybatisTest.pojo.User" flushCache="false">

Therefore, the cache will not be refreshed no matter whether or not the commit is executed. However, this will cause dirty reads and will only be used in special cases.

  • Auto refresh

In some cases, if you need to set Automatic cache refresh, You need to configure the corresponding cache tag in mapper.

flushInterval="10000"

This attribute indicates that the cache is automatically refreshed every 10 seconds.

Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.