二级缓存:
- 它指的是 Mybatis 中 SqlSessionFactory 对象的缓存。由同一个 SqlSessionFactory 对象创建的 SqlSession 共享其缓存
- 二级缓存的使用步骤
- 让 Mybatis 框架支持二级缓存(在SqlMapConfig.xml配置)
- 让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
- 让当前的操作支持二级缓存(在select标签中配置)
一、SqlMapConfig.xml
<?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 resource="jdbcConfig.properties"/>
<settings>
<!--默认为 true-->
<setting name="cacheEnabled" value="true"/>
</settings>
<typeAliases>
<package name="domain"/>
</typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="dao"/>
</mappers>
</configuration>
二、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="dao.IUserDao">
<!--开启 uer 支持二级缓存-->
<cache/>
<!--不管有没有账户,用户的信息都得有,所以不能用内连接,所以用左外连接,会返回左表的所有数据-->
<select id="findAll" resultType="user">
select *from user
</select>
<select id="findById" parameterType="integer" resultType="user" useCache="true">
select *from user where id=#{userId}
</select>
<update id="updateUser" parameterType="User">
update user set username=#{username},address=#{address} where id=#{id}
</update>
</mapper>
三、JAVA 代码
@Test
public void testFirstLevelCache(){
SqlSession sqlSession1=factory.openSession();
IUserDao dao1=sqlSession1.getMapper(IUserDao.class);
User user1=dao1.findById(1);
System.out.println(user1);
//一级缓存消失
sqlSession1.close();
SqlSession sqlSession2=factory.openSession();
IUserDao dao2=sqlSession2.getMapper(IUserDao.class);
User user2=dao2.findById(1);
System.out.println(user2);
//一级缓存消失
sqlSession1.close();
System.out.println(user1==user2);
}
四、Log 输出
Opening JDBC Connection
[DEBUG] 2019-08-17 09:09:12,364 method:org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:424)
Created connection 1634132079.
[DEBUG] 2019-08-17 09:09:12,365 method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.setDesiredAutoCommit(JdbcTransaction.java:100)
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6166e06f]
[DEBUG] 2019-08-17 09:09:12,369 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==> Preparing: select *from user where id=?
[DEBUG] 2019-08-17 09:09:12,389 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==> Parameters: 1(Integer)
[DEBUG] 2019-08-17 09:09:12,437 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
<== Total: 1
domain.User@4d49af10
[DEBUG] 2019-08-17 09:09:12,451 method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.resetAutoCommit(JdbcTransaction.java:122)
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6166e06f]
[DEBUG] 2019-08-17 09:09:12,451 method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.close(JdbcTransaction.java:90)
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@6166e06f]
[DEBUG] 2019-08-17 09:09:12,452 method:org.apache.ibatis.datasource.pooled.PooledDataSource.pushConnection(PooledDataSource.java:381)
Returned connection 1634132079 to pool.
[DEBUG] 2019-08-17 09:09:12,456 method:org.apache.ibatis.cache.decorators.LoggingCache.getObject(LoggingCache.java:60)
Cache Hit Ratio [dao.IUserDao]: 0.5
domain.User@c540f5a
false
五、总结
- 由 log 日志可知总共查询了一次,第二次是从缓存中查询的。
- 最后结果为 false,这个是因为二级缓存存储的是数据而不是对象
- {"id":1,"username":"老王","address":"北京"}
- 它会在第二次查询的时候创建一个新的对象,再把数据填充进去