mybatis查询缓存

1.一级缓存

Mybatis的一级缓存是指SqlSession。一级缓存的作用域是一个SqlSession。Mybatis默认开启一级缓存。
在同一个SqlSession中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;
第二次直接从缓存中取。当执行SQL时两次查询中间发生了增删改操作,则SqlSession的缓存清空。

2.一级缓存demo

这里根据sqlSessionFactory获取sqlsession,再用两个相同的条件用同一个sqlsession进行查询。

    @Autowired
    private SqlSessionFactory sessionFactory;

    @Test
    public void contextLoads() {
        
        SqlSession sqlSession1 = sessionFactory.openSession();
        UserDao userMapper1 = sqlSession1.getMapper(UserDao.class);
        User user = userMapper1.loadById(1l);
        User user2 = userMapper1.loadById(1l);
        sqlSession1.close();

    }

这里可以看到输出日志,只进行了一次数据查询。

JDBC Connection [HikariProxyConnection@384283650 wrapping com.mysql.jdbc.JDBC4Connection@534c6767] will not be managed by Spring
==>  Preparing: SELECT * FROM user WHERE id = ? 
==> Parameters: 1(Long)
<==    Columns: id, name
<==        Row: 1, 张三
<==      Total: 1
11:29:15.468 [Thread-2] INFO  o.s.w.c.s.GenericWebApplicationContext - Closing org.springframework.web.context.support.GenericWebApplicationContext@5b799640: startup date [Sun Sep 16 11:29:10 CST 2018]; root of context hierarchy 

这里依然还是同一个sqlsession,首先先执行查询,其次在做修改操作,再执行查询操作。

    @Autowired
    private SqlSessionFactory sessionFactory;

    @Test
    public void contextLoads() {

        SqlSession sqlSession1 = sessionFactory.openSession();
        UserDao userMapper1 = sqlSession1.getMapper(UserDao.class);
        //第一次查询,发出sql语句,并将查询的结果放入缓存中
        User user = userMapper1.loadById(1l);
        //第二步进行了一次更新操作,sqlSession.commit()
        user.setName("李四");
        userMapper1.update(user);
        sqlSession1.commit();
        //第二次查询,由于是同一个sqlSession.commit(),会清空缓存信息
        //则此次查询也会发出 sql 语句,并将查询的结果放入缓存中
        User user2 = userMapper1.loadById(1l);
        //第三次查询,从缓存中获取
        User user3 = userMapper1.loadById(1l);
        sqlSession1.close();

    }

这里可以看到输出日志,因为数据更新,缓存会被清除。

JDBC Connection [HikariProxyConnection@698437724 wrapping com.mysql.jdbc.JDBC4Connection@24db6ce] will not be managed by Spring
==>  Preparing: SELECT * FROM user WHERE id = ? 
==> Parameters: 1(Long)
<==    Columns: id, name
<==        Row: 1, 李四
<==      Total: 1
==>  Preparing: UPDATE user SET name=? WHERE id=? 
==> Parameters: 李四(String), 1(Long)
<==    Updates: 1
==>  Preparing: SELECT * FROM user WHERE id = ? 
==> Parameters: 1(Long)
<==    Columns: id, name
<==        Row: 1, 李四
<==      Total: 1
11:38:06.010 [Thread-2] INFO  o.s.w.c.s.GenericWebApplicationContext - Closing org.springframework.web.context.support.GenericWebApplicationContext@5b799640: startup date [Sun Sep 16 11:38:00 CST 2018]; root of context hierarchy 

1.二级缓存

Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,
多个SqlSession共享。Mybatis需要手动设置启动二级缓存。
在同一个namespace下的mapper文件中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;
第二次直接从缓存中取。当执行SQL时两次查询中间发生了增删改操作,则二级缓存清空。

2.一级缓存demo

和一级缓存默认开启不一样,二级缓存需要我们手动开启首先在全局配置文件 mybatis-configuration.xml 文件中加入如下代码

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

其次在 UserMapper.xml 文件中开启缓存

<!-- 开启二级缓存 -->
<cache></cache>

开启了二级缓存后,还需要将要缓存的pojo实现Serializable接口,
为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一定只存在内存中,
有可能存在硬盘中,如果我们要再取这个缓存的话,就需要反序列化了。

@Data
public class User implements Serializable {
	private static final long serialVersionUID = 7592001409898062289L;
	private Long id;
	private String name;
}

这里用两个不同sqlsession,执行数据查询

    @Autowired
    private SqlSessionFactory sessionFactory;

    @Test
    public void contextLoads() {

        SqlSession sqlSession1 = sessionFactory.openSession();
        SqlSession sqlSession2 = sessionFactory.openSession();
        UserDao userMapper1 = sqlSession1.getMapper(UserDao.class);
        UserDao userMapper2 = sqlSession2.getMapper(UserDao.class);
        //第一次查询,发出sql语句,并将查询的结果放入缓存中
        User user1 = userMapper1.loadById(1l);
        //第一次查询完后关闭sqlSession
        sqlSession1.close();
        User user2 = userMapper2.loadById(1l);
        sqlSession2.close();
    }

可以看出上面两个不同的sqlSession,第一个关闭了,第二次查询依然不发出sql查询语句

JDBC Connection [HikariProxyConnection@1004390006 wrapping com.mysql.jdbc.JDBC4Connection@29a1505c] will not be managed by Spring
==>  Preparing: SELECT * FROM user WHERE id = ? 
==> Parameters: 1(Long)
<==    Columns: id, name
<==        Row: 1, 李四
<==      Total: 1
Cache Hit Ratio [com.mljr.movies.dao.UserDao]: 0.5
12:15:58.284 [Thread-2] INFO  o.s.w.c.s.GenericWebApplicationContext - Closing org.springframework.web.context.support.GenericWebApplicationContext@5b799640: startup date [Sun Sep 16 12:15:52 CST 2018]; root of context hierarchy 

这里执行更新操作,二级缓存数据清空

    @Autowired
    private SqlSessionFactory sessionFactory;

    @Test
    public void contextLoads() {
        SqlSession sqlSession1 = sessionFactory.openSession();
        SqlSession sqlSession2 = sessionFactory.openSession();
        SqlSession sqlSession3 = sessionFactory.openSession();
        SqlSession sqlSession4 = sessionFactory.openSession();
        UserDao userMapper1 = sqlSession1.getMapper(UserDao.class);
        UserDao userMapper2 = sqlSession2.getMapper(UserDao.class);
        UserDao userMapper3 = sqlSession3.getMapper(UserDao.class);
        UserDao userMapper4 = sqlSession4.getMapper(UserDao.class);
        //第一次查询,发出sql语句,并将查询的结果放入缓存中
        User user1 = userMapper1.loadById(1l);
        //第一次查询完后关闭sqlSession
        sqlSession1.close();
        //执行更新操作,清空缓存
        user1.setName("王二");
        userMapper2.update(user1);
        sqlSession2.commit();
        sqlSession2.close();
        //第二次查询,发出sql语句,并将查询的结果放入缓存中
        User user3 = userMapper3.loadById(1l);
        sqlSession3.close();
        //第三次查询用缓存获取
        User user4 = userMapper4.loadById(1l);
        sqlSession4.close();
    }

这里可以看到控制台情况,第一次查询输出sql,放入缓存;第二次更新操作,清空缓存;第三次查询因为缓存清空获取不到,所以再次输出sql;第四次查询,从缓存中获取。

JDBC Connection [HikariProxyConnection@1739653374 wrapping com.mysql.jdbc.JDBC4Connection@44b18fe4] will not be managed by Spring
==>  Preparing: SELECT * FROM user WHERE id = ? 
==> Parameters: 1(Long)
<==    Columns: id, name
<==        Row: 1, 王二
<==      Total: 1
JDBC Connection [HikariProxyConnection@688722159 wrapping com.mysql.jdbc.JDBC4Connection@44b18fe4] will not be managed by Spring
==>  Preparing: UPDATE user SET name=? WHERE id=? 
==> Parameters: 王二(String), 1(Long)
<==    Updates: 1
Cache Hit Ratio [com.mljr.movies.dao.UserDao]: 0.0
JDBC Connection [HikariProxyConnection@1682828548 wrapping com.mysql.jdbc.JDBC4Connection@44b18fe4] will not be managed by Spring
==>  Preparing: SELECT * FROM user WHERE id = ? 
==> Parameters: 1(Long)
<==    Columns: id, name
<==        Row: 1, 王二
<==      Total: 1
Cache Hit Ratio [com.mljr.movies.dao.UserDao]: 0.3333333333333333
12:24:33.618 [Thread-2] INFO  o.s.w.c.s.GenericWebApplicationContext - Closing org.springframework.web.context.support.GenericWebApplicationContext@5b799640: startup date [Sun Sep 16 12:24:28 CST 2018]; root of context hierarchy 

mybatis中还可以配置userCache和flushCache等配置项
userCache是用来设置是否禁用二级缓存的,
在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,
默认情况是true,即该sql使用二级缓存。

    <!-- 根据id查询 -->
    <select id="loadById" resultMap="userResultMap" useCache="false">
		SELECT *  FROM user WHERE id =
		#{id}
	</select>

设置statement配置中的flushCache=”true” 属性,默认情况下为true,
即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。

    <!-- 根据id查询 -->
    <select id="loadById" resultMap="userResultMap" flushCache="false">
		SELECT *  FROM user WHERE id =
		#{id}
	</select>

 

 

 

 

 

 

转载于:https://my.oschina.net/u/3056927/blog/2051966

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值