mybatis deferred loading and caching

Keywords: Java Mybatis Cache

preface

Tip: Here you can add the general contents to be recorded in this article:
For example, with the continuous development of artificial intelligence, machine learning technology is becoming more and more important. Many people have started learning machine learning. This paper introduces the basic content of machine learning.

Tip: the following is the main content of this article. The following cases can be used for reference

1, mybaits delayed loading

1.1 delayed loading is also called lazy load

Lazy mode in Lenovo singleton (new when needed, not new when not needed)
Call this sql when needed and not when not needed

Lazy singleton classic code:	
getIntence(){
if(object==null){
new object
}
return object }

Necessity of 1.2mybatis delayed loading:

   the operation on the database belongs to the operation of IO stream, which is extremely inefficient, because the data is persistent in the hard disk, and the reading of IO stream is online.
  why is the bufferer in io efficient? It is because new creates a byte array, which is stored in memory as a cache,
   io has high efficiency in reading and writing memory, but low efficiency in reading and writing hard disk. When my query efficiency of data is very low, I only query the relevant information of users, but also query the relevant information of shopping cart, which will greatly enhance the burden of database
   the pressure on the server in a system is the greatest, so many optimizations are aimed at the database. When the hardware is certain, the higher the query efficiency, the better the user experience. Moreover, the hardware has limits and can not grow indefinitely, so it needs to delay loading.

In association query, only when the associated data is used can the data be really queried in the database, which can reduce the pressure on the database and improve the query efficiency,

1.3 use of mybatis delayed loading (query user and shopping cart information)

1.3.1 start delay loading

Because delayed loading is turned off by default, it needs to be turned on in the xml core configuration file and set to true

<!--        Delayed load on-->
lazyLoadingEnabled Global switch for delayed loading
        <setting name="lazyLoadingEnabled" value="true"/>

1.3.2 modifying sql statements

select * from cart c ,user u where u.id=c.userId

Because a statement must be executed without delaying loading, it is necessary to split the sql statement
sql1 query user

	  select * from cart 

sql2 check shopping cart//**///*

	  select * from cart c where c.userId=Value (should be userid)

When only the user's relevant information is queried, only sql1 is used. When the shopping cart needs to be queried, both items are executed

1.3.3 code case

1.3.3.1 add abstract method in UserMapper

/**
     * Use lazy loading to query user and shopping cart information
     */
    List<User> selectUserAndCartByLazyLoad();

1.3.3.2 add configuration in UserMapper.xml

<!--
select:The full pathname must be written for the method to be executed
column:id   Indicates that it will select * from user The result of id The value of the column is passed to select Label specifies the parameters of the method
-->
 <resultMap id="lazyMap" type="user">
    <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <result property="address" column="address"></result>
  	<association property="cart" javaType="cart" 
  select="com.shangma.cn.mapper.CartMapper.selectCartById"
         column="id"></association>
    </resultMap>
<select id="selectUserAndCartByLazyLoad" resultMap="lazyMap">
        select * from user
 </select>

1.3.3.3 add in CartMapper (the method of querying shopping cart based on id)

/**
     * Query shopping cart by id
     */
    Cart selectCartById(int userId);

1.3.3.4 add configuration in CartMapper.xml

<select id="selectCartById" resultType="cart">
        select * from cart where userId = #{id}
    </select>

1.3.3.5 interpretation

    the value of id in UserMapper.xml, column="id" is the value of id in the query result in select * from user, and the obtained id value is passed to the method in select, that is, to the following code method as a parameter to find out the relevant information of the shopping cart

 <select id="selectCartById" resultType="cart">
        select * from cart where userId = #{id}
    </select>

When the global switch of lazy loading enabled delayed loading is turned on in the configuration, it will be judged dynamically

 <association property="cart" javaType="cart" select="com.shangma.cn.mapper.CartMapper.selectCartById" column="id"></association>

Whether to execute.

1.3.3.6 test results

During the test, it is found that if only the basic information of the user is obtained, the select * from cart where userId = #{id} statement will not be executed

If you explicitly specify to get the shopping cart information, the select * from cart where userId = #{id} statement will be executed

2, Cache concept

1. Why cache

  • Reduce the pressure on the database, because the database is an IO operation (the operation is the data in the hard disk), and the efficiency is low (like pulling a thing from the desktop and putting it in Disk c, there will be a slow progress bar).
  • Price pressure, disk hardware is more expensive
  • High memory reading and writing efficiency

2. Cache idea

All caching is an idea

  • Look for data in the cache every time
  • If it is the first time to search, there is no data, and then go to the database to find it
  • If it is the first search, the data is found in the database and then returned to the cache
  • In the future, each search will first find it in the cache
  • The result is not found in the database, and the result is cached to return

2.1 drawing demonstration

2.2 cache benefits

  • Improve user experience
  • Reduce database pressure
  • Increase reading speed

2.2 cache drawbacks

The memory of the server is basically unused most of the time. Generally, the operations of adding, deleting and modifying and writing to the database are direct, and only the query is the cache

  • The data queried is not the latest data (ticket grabbing, gun, mobile phone)

2.2 solutions to cache drawbacks

  • 1. Real time update (update the cache every time you write to the database), which is the most stupid way and greatly reduces the efficiency
  • 2. Set the expiration time (set the expiration time of different caches according to business requirements (12306 is basically one minute))
    That is, the data is stored in the cache. The effective time is one minute. After one minute, it will become invalid. Go to the database again
  • 3. The data is directly stored in the cache, and the data in the cache is regularly updated to the database
  • 4. Execute DML (add, delete, change) and update the cache

conclusion

It is impossible to completely solve the cache problem, and the efficiency of query and the correctness of data cannot be guaranteed at the same time
Without caching, the database will jump when the number of queries is too many

3, mybatis cache

3.1. L1 cache

3.1.1 test (on by default)

The L1 cache is a sqlSession level cache, or a transaction level cache, and is enabled by default, so

/**
     * Test the first level cache of mybatis
     */
    @Test
    public void test12(){
        // Use the same sql and the same sqlSession to query twice, and execute the sql statement for the first time (query the data in the database)
        // The second time is the data obtained from the cache
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.findUserById(44);
        System.out.println(user);

        UserMapper mapper1 = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper1.findUserById(44);
        System.out.println(user1);
    }

3.1.2 L1 cache analysis

When querying users with id for the first time, there is no sql in the cache. When querying users for the second time, there is data in the cache and sql statements are not executed

3.2. L2 cache

The L2 cache of mybatis is off by default. It is a sqlSessionFactory level cache, or a mapper interface, which is a namespace level cache.

3.2.1 L2 cache analysis

When using a query, the query results are stored in the corresponding namespace level

When the DML statement is executed at the namespace level, the cache will be emptied

The L2 cache may be stored in memory or hard disk.

The L2 cache expiration time is one hour

Using L2 caching, entity classes need to implement serialization interfaces
Serialization: you can convert an object (type of flag object) and its state into bytecode, save it (it can be saved in database, memory, file, etc.), and then restore its state (that is, deserialization) at an appropriate time

3.2.1 L2 cache usage

  • Write the * * < cache / > * * tag in the xml that needs to open the L2 cache
  • The L2 cache must commit a transaction to take effect

3.2.1.1 write the * * < cache / > * * tag in the xml that needs to open the L2 cache

 Enable L2 cache
    <cache/>

3.2.1.2 verification

/**
     * Testing the L2 cache of mybatis
     */
    @Test
    public void test13(){
        // start transaction
        // Execute sql
        // rollback
        // commit
        // Different sqlsessions must be used in the L2 cache to verify
        // Because if I use the same sqlSession, I verify the L1 cache
        SqlSession sqlSession = sqlSessionFactory.openSession();
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(mapper.findUserById(44));
        sqlSession.commit();
        sqlSession.close();

        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        System.out.println(mapper1.findUserById(44));
        sqlSession1.commit();
        sqlSession1.close();

        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        System.out.println(mapper2.findUserById(44));
        sqlSession2.commit();
        sqlSession2.close();
    }

Posted by bradleyy on Sun, 05 Dec 2021 06:59:59 -0800