Mybatis之缓存

1.Mybatis的底层工作原理

此详细过程请看前博客 “Mybatis的工作原理”

2.测试缓存的环境准备

利用idea+maven+junit搭建一个项目,如果此步骤还不熟
请参照IDEA 之maven+junit构建

然加入jdbc依赖 ,log4j2所需的依赖:

 <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.38</version>
            </dependency>

            <!-- https://mvnrepository.com/artifact/com.oracle/ojdbc14 -->
            <dependency>
                <groupId>com.oracle</groupId>
                <artifactId>ojdbc14</artifactId>
                <version>10.2.0.3.0</version>
            </dependency>

            <!--添加log4j2依赖-->
            <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-core</artifactId>
                <version>2.8.2</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/log4j/log4j -->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-api</artifactId>
                <version>2.8.2</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-slf4j-impl</artifactId>
                <version>2.8.2</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-web -->
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-web</artifactId>
                <version>2.8.2</version>
            </dependency>

要看到mybatis的缓存就必须,通过日志来跟踪sql,所以还要整合log4j2。

log4j2的配置:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <!--输出的目的地-->
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %l %msg%n"/>
        </Console>
    </Appenders>

    <Loggers>
        <!--其他的日志以 error 为级别 ,除非有logger 覆盖 如下-->
        <Root level="error">
            <AppenderRef ref="Console"/>
        </Root>

        <!-- mapper结构所在的包-->
        <Logger name="com.worldly.config.mapper" level="TRACE" additivity="false">
            <AppenderRef ref="Console"/>
        </Logger>
    </Loggers>
</Configuration>  

用junit测试selectEmployeeList可以看到如下console输出,就说明环境已经准备好了。
这里写图片描述

3.Mybatis的缓存

3.1 mybatis的一级缓存SqlSession缓存

sqlSession缓存是默认开启的,在一个sqlSession在使用select的时候会先从本地缓存中读,如果没有才会连接数据库查询相关的数据,然后将查询的数据放入本地缓存,以便下次select。只要事务不提交( 增删该等动作)或者没有sqlSession.close(), 执行查询条件相同的第二次查询,就直接从缓存中取,不发sql。

 @Test
    public void testCache1() {
        InputStream resourceAsStream = ConfigTest.class.getResourceAsStream("../classes/mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //查询id为1的员工
        Employee param = new Employee();
        param.setId(1);


        /**
         * 1用sqlSession 获取mapper的代理对象 执行按条件查询,
         * 由于是第一次查询,缓存中没有,会发出查询sql
         */
        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
        Employee employee = mapper.selectEmployeeByCondition(param);
        System.out.println(employee);

        /**
         * 用同一sqlSession 获取mapper的代理对象 执行与1相同的查询
         * 1查询后缓存中有数据,如果是相同的查询就直接从缓存中取,不发sql语句
         */
        EmployeeMapper mapper2 = sqlSession.getMapper(EmployeeMapper.class);
        Employee employee2 = mapper2.selectEmployeeByCondition(param);
        System.out.println(employee2);


        //触发事务commit
        sqlSession.commit();

        /**
         * 事务提交。本地缓存清空
         * 虽然同sqlSession 执行为条件相同的查询,但还是要connection  db 进行select
         */
        EmployeeMapper mapper3 = sqlSession.getMapper(EmployeeMapper.class);
        Employee employee3 = mapper3.selectEmployeeByCondition(param);
        System.out.println(employee3);
    }

这里写图片描述

3.2 mybatis的二级缓存Mapper级别的缓存

mybatis的二级缓存是namespace级别的,就是同一Mapper下的多个sqlSession共享一个缓存。因此只要有一个sqlSession发出了一个查询,第二sqlSession发出同样的查询的话,是直接从二级缓存中取数据的。
二级缓存默认不开启,如果要使用的话要在mybatis-config.xml的全局配置文件中开启,同时要在mapper 的sql映射文件中配置cache, 此外缓存的对象 必须 implments Serializable接口。

<!--配置缓存的全局开关 如果要使用缓存 就必须设置-->
<setting name="cacheEnabled" value="true"/>

<!--mapper映射文件中的开启-->
<?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.worldly.config.mapper.EmployeeMapper">
    <!--开启缓存,如果不设置就默认使用mybatis自身的二级缓存-->
    <cache/>

    <resultMap id="empResultMap" type="com.worldly.config.entity.Employee">
        <id column="emp_id" property="id"></id>
        <result column="emp_name" property="name"/>
        <result column="emp_email" property="email"/>
        <result column="emp_tel" property="tel"/>
        <result column="emp_dep" property="depId"/>
    </resultMap>

    <select id="selectEmployeeList" resultMap="empResultMap" databaseId="mysql">
        select * from t_emp
    </select>

    <select id="selectEmployeeByCondition" resultMap="empResultMap" databaseId="mysql">
        select * from t_emp WHERE emp_id=#{param.id}
    </select>
</mapper>

我们用两个sqlSession去查询同一sql, 看是否会发出sql
测试代码:

 @Test
    public void testCache2() {
        InputStream resourceAsStream = ConfigTest.class.getResourceAsStream("../classes/mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //查询id为1的员工
        Employee param = new Employee();
        param.setId(1);


        /**
         * 1用sqlSession 获取mapper的代理对象 执行按条件查询,
         * 由于是第一次查询,缓存中没有,会发出查询sql
         */
        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
        Employee employee = mapper.selectEmployeeByCondition(param);
        System.out.println(employee);

        //触发事务commit
        sqlSession.commit();

        /**
         * 用同一sqlSession 获取mapper的代理对象 执行与1相同的查询
         * 1查询后缓存中有数据,如果是相同的查询就直接从缓存中取,不发sql语句
         */
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        EmployeeMapper mapper2 = sqlSession2.getMapper(EmployeeMapper.class);
        Employee employee2 = mapper2.selectEmployeeByCondition(param);
        System.out.println(employee2);

    }

mybatis二级缓存测试输出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值