1. Why cache is used in the program

For our programming, caching means storing frequently invoked objects (temporary data) in memory so that they can be called quickly when used without having to create new and repeated instances. Doing so can reduce system overhead and improve efficiency. After a certain understanding of the cache, we know that the use of cache is to reduce the number of interactions with the database and improve the efficiency of execution. Which brings us to the next question. What data can and cannot be used in the cache? This is something we have to be explicit about when we use caching, and it actually applies to cached data: frequently queried and infrequently changed, and whether the data is correct or not makes little difference to the final result; Not applicable to cached data: data that changes frequently, and whether the data is correct or not has a significant impact on the final result. Mybatis level 1 cache and level 2 cache in the end what cache, cache after what effect, when the cache data will be cleared? Level 1 cache: It refers to the cache of sqlSession object in Mybatis. After we execute the query, the query result will be stored in a region provided by sqlSession. The structure of this region is a Map. Mybatis will first go to sqlSession to check whether there is any, if there is any direct use, when sqlSession object disappeared, Mybatis level cache also disappeared, at the same time level cache is SQLSESSION scope cache, The level 1 cache is cleared when the SqlSession modify, add, delete, commit(),close, and other methods are called. Level 2 cache: Sqlsessions created by the same SqlSessionFactory object share the cache, but it caches data instead of objects. So the object queried from the second level cache is not the same as the object saved the first time. Use a simple example to further understand level 1 and level 2 caches.

1. Level 1 cache

1. The user class

public class User implements Serializable{ private Integer id; private String username; private Date birthday; private String sex; private String address; The get and set methods omit..... }Copy the code

2. The Dao layer

Public interface UserMapper {** ** query all users ** @return */ List<User> findAll(); /** * query User by Id ** @return */ User findById(Integer Id); /** * updateUser * @param user */ void updateUser(user user); }Copy the code

3. Usermapper. XML mapping file

<mapper namespace="com.example.mapper.UserMapper"> <select id="findAll" resultType="com.example.domain.User"> SELECT * FROM USER; </select> <select id="findById" resultType="com.example.domain.User" parameterType="INT"> SELECT * FROM USER WHERE ID = #{ID} </select> <update id="updateUser" parameterType="com.example.domain.User"> update USER <set> <if test="username ! = null">username=#{username},</if> <if test="password ! = null">birthday=#{birthday},</if> <if test="sex ! = null">sex=#{sex},</if> <if test="address ! = null">address=#{address},</if> </set> where id=#{id} </update> </mapper>Copy the code

4. Configure MyBatis to print logs

<settings> <! <setting name="logImpl" value="STDOUT_LOGGING" /> </ Settings >Copy the code

The above is the single table operation of Mybatis. The following is to observe the difference between the effectiveness of level 1 cache by querying the user’s operation according to the user ID.

5. Test

(1) Test code for matching level 1 cache

public class MapperProxyTest { private SqlSessionFactory sqlSessionFactory; @Before public void init() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); } @Test public void findByIdTest(){ SqlSession sqlSessions = sqlSessionFactory.openSession(); UserMapper userDao = sqlSessions.getMapper(UserMapper.class); User1 = userdao.findById (45); System.out.println(user1); User user2 = userdao.findById (45); System.out.println(user2); System.out.println(user1 == user2); sqlSessions.close(); }}Copy the code

Test results:

(2) SqlSession to clear the cache operation, that is, clear level cache, and then test again.

@Test public void findByIdTest(){ SqlSession sqlSessions = sqlSessionFactory.openSession(); UserMapper userDao = sqlSessions.getMapper(UserMapper.class); User user1 = userDao.findById(45); System.out.println(user1); //session.commit(); Call SqlSession commit to clear cache user1.setusername (" update user "); User1.setaddress (" update address "); userDao.updateUser(user1); // Clear cache by updating SqlSession User user2 = userdao.findById (45); System.out.println(user2); System.out.println(user1 == user2); sqlSessions.close(); }Copy the code

There are many ways to clear the cache, so try them all. Test results:

2. Level 2 cache

Take a look at how the Mybatis level 2 cache is used. The first step is to have the Mybatis framework support level 2 caching (configured in the Mybatis main configuration file), the second step is to have the current mapping file support level 2 caching (configured in the Dao.xml mapping file), and the third step is to have the current method support level 2 caching (configured in the tag). Follow this step to configure the query user interface above to support level 2 caching.

1. Configure Mybatis framework to support level 2 caching

1. Configure Mybatis framework to support level 2 caching

<setting name="cacheEnabled" value="true"/>
Copy the code

2. Configure usermapper. XML to support level-2 cache

 <cache/>
Copy the code

3. Configure the query method to support level-2 cache

<select id="findById" resultType="com.example.domain.User" parameterType="INT" useCache="true"> SELECT * FROM USER WHERE  ID = #{ID} </select>Copy the code

4. Test

@ Test public void findByIdTest () {/ / query for the first time And update the second level cache SqlSession session. = sqlSessionFactory openSession (); UserMapper userDao1 = session.getMapper(UserMapper.class); User user1 = userDao1.findById(45); System.out.println(user1); session.commit(); //commit() commits level 2 cache and clears level 1 cache session.close(); // // user1.setusername (" update user "); // user1.setAddress(" update address "); // userDao.updateUser(user1); By updating the SqlSession to empty the cache / / / / the second lookup hit the second level cache SqlSession session1 = sqlSessionFactory. OpenSession (); UserMapper userDao2 = session1.getMapper(UserMapper.class); User user2 = userDao2.findById(45); session1.commit(); Session1.close (); session1.close(); session1.close(); // System.out.println(user2); System.out.println(user1 == user2); }Copy the code

Test results:

3. Summary

Mybatis level 1 cache is the SqlSession level cache. Level 1 cache is used to cache objects. When SqlSession commits, closes, and other database updates occur, level 1 cache is cleared. Level-2 cache is the cache at SqlSessionFactory level. Sqlsessions generated by the same SqlSessionFactory share a level-2 cache. Level-2 cache stores data. When querying data, the query process is level 2 cache > Level 1 cache > database.