Mybatis series 9- cache

Like most of persistence frameworks, Mybatis also provides a caching strategy to reduce the number of database queries by caching strategies to improve performance.
Mybatis cache is divided into a cache, L2 cache.
Level cache is SqlSession level cache, as long as SqlSession no flush or close, it exists.
Level cache is a cache SqlSession range, when you call to modify the SqlSession, add, delete, commit (), close () method, etc., it will empty the cache.

A mapper mapping the secondary cache level cache, a plurality SqlSession sql statement to operate the same Mapper maps, can share SqlSession plurality of secondary cache, the secondary cache across the SqlSession.

Cache

In order to see more clearly, to re-create a maven project
1, pom file:

<packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

2、resource创建log4j.properties、jdbcConfig.properties、SqlMapConfig.xml

# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db2
jdbc.username=root
jdbc.password=123456
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 配置properties-->
    <properties resource="jdbcConfig.properties"></properties>

    <!--<settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>-->

    <!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
    <typeAliases>
        <package name="com.mantishell.domain"></package>
    </typeAliases>

    <!--配置环境-->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务 -->
            <transactionManager type="JDBC"></transactionManager>

            <!--配置连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <!-- 配置映射文件的位置 -->
    <mappers>
        <package name="com.mantishell.dao"></package>
    </mappers>
</configuration>

3, create a configuration file persistence layer com / mantishell.dao / IUserDao.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mantishell.dao.IUserDao">
    <!--开启二级缓存-->
    <!--<cache />-->

    <!-- 查询所有 -->
    <select id="findAll" resultType="user">
        select * from user
    </select>

    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="INT" resultType="user" useCache="true">
        select * from user where id = #{uid}
    </select>

    <!-- 更新用户信息-->
    <update id="updateUser" parameterType="user">
        update user set username=#{username},address=#{address} where id=#{id}
    </update>
</mapper>

4, create entity

package com.mantishell.domain;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {
    private Integer id;
    private String username;
    private String address;
    private String sex;
    private Date birthday;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}

5, persistence layer interface:

package com.mantishell.dao;

import com.mantishell.domain.User;

import java.util.List;

public interface IUserDao {
    /**
     * 查询所有用户,同时获取到用户下所有账户的信息
     * @return
     */
    List<User> findAll();


    /**
     * 根据id查询用户信息
     * @param userId
     * @return
     */
    User findById(Integer userId);

    /**
     * 更新用户信息
     * @param user
     */
    void updateUser(User user);
}

6, the test

/**
     * 测试一级缓存
     */
    @Test
    public void testFirstLevelCache(){
        User user1 = userDao.findById(41);
        System.out.println(user1);

        userDao = sqlSession.getMapper(IUserDao.class);

        User user2 = userDao.findById(41);
        System.out.println(user2);

        System.out.println(user1 == user2);
    }

The results are:

com.mantishell.domain.User@282003e1
2020-03-17 22:16:36,821 554    [           main] DEBUG    com.mantishell.dao.IUserDao  - Cache Hit Ratio [com.mantishell.dao.IUserDao]: 0.0
com.mantishell.domain.User@282003e1
true

And did not go to the database lookup can be seen in the second query, but taken from the cache.

When sqlSession shut off or empty the cache:

@Test
    public void testFirstLevelCache(){
        User user1 = userDao.findById(41);
        System.out.println(user1);

        sqlSession.close();
        //再次获取SqlSession对象
        sqlSession = factory.openSession();

        //sqlSession.clearCache();//此方法也可以清空缓存

        userDao = sqlSession.getMapper(IUserDao.class);

        User user2 = userDao.findById(41);
        System.out.println(user2);

        System.out.println(user1 == user2);
    }

The results are:

com.mantishell.domain.User@6e2c9341
2020-03-17 22:26:28,239 619    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@543e710e]
2020-03-17 22:26:28,239 619    [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 1413378318 to pool.
2020-03-17 22:26:28,239 619    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Opening JDBC Connection
2020-03-17 22:26:28,240 620    [           main] DEBUG source.pooled.PooledDataSource  - Checked out connection 1413378318 from pool.
2020-03-17 22:26:28,240 620    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@543e710e]
2020-03-17 22:26:28,242 622    [           main] DEBUG ntishell.dao.IUserDao.findById  - ==>  Preparing: select * from user where id = ? 
2020-03-17 22:26:28,242 622    [           main] DEBUG ntishell.dao.IUserDao.findById  - ==> Parameters: 41(Integer)
2020-03-17 22:26:28,247 627    [           main] DEBUG ntishell.dao.IUserDao.findById  - <==      Total: 1
com.mantishell.domain.User@4e4aea35
false

Obviously query twice from the database.

Secondary cache

Secondary cache is mappermapped level cache, a plurality SqlSession sql statement to operate the same Mapper maps, you can share SqlSession plurality of secondary cache, the secondary cache across SqlSessionthe.

Need to manually open the secondary cache
sqlSession1 queries the user information, query the user information query data will be stored in the secondary cache.
At this time, if SqlSession3 sql statement to execute at the same mapper mapping commit the execution, it will clear the data in the secondary cache area of the mapper maps.
SqlSession2 to query the same SqlSession1 user information, will first go to find whether there is data in the cache, if there is data taken directly from the cache.

Opening and closing the secondary cache

1, open second-level cache file SqlMapConfig.xml

    <!--开启二级缓存-->
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>

cacheEnabled default values ​​are true, so this step can be omitted. It represents true- open; false-off represents

2, the configuration file modified persistence

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mantishell.dao.IUserDao">
    <!--开启二级缓存-->
    <cache />

    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="INT" resultType="user" useCache="true">
        select * from user where id = #{uid}
    </select>

<select>Tag set useCache = "true" represents the current statement to be used in this secondary cache, if the secondary cache is not used can be set to false.
Note: If you need the latest data for each query, you need to set useCache = false, disable L2 cache.

test:

    @Test
    public void testFirstLevelCache(){
        SqlSession sqlSession1 = factory.openSession();
        IUserDao dao1 = sqlSession1.getMapper(IUserDao.class);
        User user1 = dao1.findById(41);
        System.out.println(user1);
        sqlSession1.close();//一级缓存消失

        SqlSession sqlSession2 = factory.openSession();
        IUserDao dao2 = sqlSession2.getMapper(IUserDao.class);
        User user2 = dao2.findById(41);
        System.out.println(user2);
        sqlSession2.close();

        System.out.println(user1 == user2);
    }

First, turn off the cache, so as not to affect future results. From the results, the two values ​​sql query is executed only once, that is taken from the secondary cache

2020-03-17 22:54:17,508 287    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Opening JDBC Connection
2020-03-17 22:54:17,904 683    [           main] DEBUG source.pooled.PooledDataSource  - Created connection 392781299.
2020-03-17 22:54:17,904 683    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@17695df3]
2020-03-17 22:54:17,912 691    [           main] DEBUG ntishell.dao.IUserDao.findById  - ==>  Preparing: select * from user where id = ? 
2020-03-17 22:54:17,934 713    [           main] DEBUG ntishell.dao.IUserDao.findById  - ==> Parameters: 41(Integer)
2020-03-17 22:54:17,959 738    [           main] DEBUG ntishell.dao.IUserDao.findById  - <==      Total: 1
com.mantishell.domain.User@282003e1
2020-03-17 22:54:17,967 746    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@17695df3]
2020-03-17 22:54:17,968 747    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@17695df3]
2020-03-17 22:54:17,968 747    [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 392781299 to pool.
2020-03-17 22:54:17,972 751    [           main] DEBUG    com.mantishell.dao.IUserDao  - Cache Hit Ratio [com.mantishell.dao.IUserDao]: 0.5
com.mantishell.domain.User@5606c0b

Guess you like

Origin www.cnblogs.com/mantishell/p/12509456.html