Mybatis 一级缓存和引发的问题

1.Mybatis 是默认开启一级缓存的。跟Spring结合使用的话执行的方法必须开启事务一级缓存才有效。
2.当查询数据时候,先从缓存中寻找是否存在该条数据,存在就直接取出来,不存在,向数据库发送sql查询, 然后将查询后的数据存入缓存返回给程序。

下边围绕着如下几个问题展开验证:

  1. 开启事务,一级缓存有效
  2. 不开启事务,一级缓存失效
  3. Mybatis一级缓存的坑在哪呢?
  4. 验证一个事物中进行insert update delete 会刷新一级缓存

二 验证

1.开启事务,一级缓存有效。从日志看到确实只执行了一次查询。


@Test
@Transactional
public void test() {
	LangUser langUser = langUserMapper.selectByPrimaryKey(-1);
	LangUser langUser1 = langUserMapper.selectByPrimaryKey(-1);
	LangUser langUser2 = langUserMapper.selectByPrimaryKey(-1);

}
15:58:20.584 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
15:58:20.594 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@63648ee9]
15:58:21.095 [main] WARN  com.alibaba.druid.pool.DruidDataSource - removeAbandoned is true, not use in productiion.
15:58:21.872 [main] INFO  com.alibaba.druid.pool.DruidDataSource - {dataSource-1} inited
15:58:21.899 [main] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@4351171a] will be managed by Spring
15:58:21.902 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==>  Preparing: select ID, NAME, AGE, SCORE from LANG_USER where ID = ? 
15:58:21.974 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Parameters: -1(Integer)
15:58:22.013 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==    Columns: ID, NAME, AGE, SCORE
15:58:22.020 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==        Row: -1, 小狼, 18, 100
15:58:22.022 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==      Total: 1
15:58:22.024 [main] DEBUG com.alibaba.druid.pool.PreparedStatementPool - {conn-10004, pstmt-20000} enter cache

2.不开启事务,一级缓存失效

@Test
public void test() {
	LangUser langUser = langUserMapper.selectByPrimaryKey(-1);
	LangUser langUser1 = langUserMapper.selectByPrimaryKey(-1);
	LangUser langUser2 = langUserMapper.selectByPrimaryKey(-1);
}

注意看日志打印,下面这句话执行了出现了三次,每一次查询都创建了一个sqlSeesion,sql也执行了三次。

16:02:29.606 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession

16:02:29.606 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
16:02:29.612 [main] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4c6daf0] was not registered for synchronization because synchronization is not active
16:02:29.863 [main] WARN  com.alibaba.druid.pool.DruidDataSource - removeAbandoned is true, not use in productiion.
16:02:31.175 [main] INFO  com.alibaba.druid.pool.DruidDataSource - {dataSource-1} inited
16:02:31.224 [main] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3088660d] will not be managed by Spring
16:02:31.230 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==>  Preparing: select ID, NAME, AGE, SCORE from LANG_USER where ID = ? 
16:02:31.335 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Parameters: -1(Integer)
16:02:31.397 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==    Columns: ID, NAME, AGE, SCORE
16:02:31.409 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==        Row: -1, 小狼, 18, 100
16:02:31.413 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==      Total: 1
16:02:31.414 [main] DEBUG com.alibaba.druid.pool.PreparedStatementPool - {conn-10004, pstmt-20000} enter cache
16:02:31.417 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4c6daf0]
16:02:31.420 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
16:02:31.422 [main] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@272a179c] was not registered for synchronization because synchronization is not active
16:02:31.423 [main] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3088660d] will not be managed by Spring
16:02:31.425 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==>  Preparing: select ID, NAME, AGE, SCORE from LANG_USER where ID = ? 
16:02:31.426 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Parameters: -1(Integer)
16:02:31.430 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==    Columns: ID, NAME, AGE, SCORE
16:02:31.430 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==        Row: -1, 小狼, 18, 100
16:02:31.431 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==      Total: 1
16:02:31.435 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@272a179c]
16:02:31.435 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
16:02:31.437 [main] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@67207d8a] was not registered for synchronization because synchronization is not active
16:02:31.438 [main] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3088660d] will not be managed by Spring
16:02:31.439 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==>  Preparing: select ID, NAME, AGE, SCORE from LANG_USER where ID = ? 
16:02:31.442 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Parameters: -1(Integer)
16:02:31.444 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==    Columns: ID, NAME, AGE, SCORE
16:02:31.444 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==        Row: -1, 小狼, 18, 100
16:02:31.444 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==      Total: 1
16:02:31.445 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@67207d8a]
16:02:31.480 [Thread-1] INFO  com.alibaba.druid.pool.DruidDataSource - {dataSource-0} closing ...
16:02:31.484 [Thread-1] INFO  com.alibaba.druid.pool.DruidDataSource - {dataSource-1} closing ...
16:02:31.589 [Thread-1] INFO  com.alibaba.druid.pool.DruidDataSource - {dataSource-1} closed

3.坑在哪呢?我们看这种开启事务的情况。

第一次查询后,我只是把查询出来的对象赋值“喜洋洋”,我并没有跟数据库有任何交互,下面的两次查询结果竟然修改后的“喜洋洋”。

@Test
@Transactional
public void test() {
	LangUser langUser = langUserMapper.selectByPrimaryKey(-1);
	logger.info("姓名:"+langUser.getName());
	langUser.setName("喜洋洋");
	LangUser langUser1 = langUserMapper.selectByPrimaryKey(-1);
	logger.info("姓名:"+langUser1.getName());
	LangUser langUser2 = langUserMapper.selectByPrimaryKey(-1);
	logger.info("姓名:"+langUser2.getName());
}
16:16:22.983 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
16:16:22.991 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@117e0fe5]
16:16:23.437 [main] WARN  com.alibaba.druid.pool.DruidDataSource - removeAbandoned is true, not use in productiion.
16:16:24.423 [main] INFO  com.alibaba.druid.pool.DruidDataSource - {dataSource-1} inited
16:16:24.459 [main] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3c2772d1] will be managed by Spring
16:16:24.463 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==>  Preparing: select ID, NAME, AGE, SCORE from LANG_USER where ID = ? 
16:16:24.575 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - ==> Parameters: -1(Integer)
16:16:24.604 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==    Columns: ID, NAME, AGE, SCORE
16:16:24.612 [main] TRACE com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==        Row: -1, 小狼, 18, 100
16:16:24.615 [main] DEBUG com.hao.xu.lang.mapper.oracle.LangUserMapper.selectByPrimaryKey - <==      Total: 1
16:16:24.617 [main] DEBUG com.alibaba.druid.pool.PreparedStatementPool - {conn-10004, pstmt-20000} enter cache
16:16:24.618 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@117e0fe5]
16:16:24.618 [main] INFO  com.hao.xu.lang.mapper.oracle.LangUserMapperTest - 姓名:小狼
16:16:24.620 [main] INFO  com.hao.xu.lang.mapper.oracle.LangUserMapperTest - 姓名:喜洋洋
16:16:24.621 [main] INFO  com.hao.xu.lang.mapper.oracle.LangUserMapperTest - 姓名:喜洋洋
16:16:24.622 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@117e0fe5]
16:16:24.623 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@117e0fe5]

原因:
当数据库建立一次连接,就会创建一个SqlSession对象,默认是DefaultSqlSession这个实现,这个对象给用户提供了操作数据库的各种方法,与此同时,也会创建一个Executor执行器,缓存信息就是维护在Executor中,如果这个sqlSessio进行
insert update delete 它会释放掉Executor中的缓存

4.验证一个事物中进行insert update delete 会刷新一级缓存

@Test
@Transactional
public void test() {
	LangUser langUser = langUserMapper.selectByPrimaryKey(-1);
	logger.info("姓名:"+langUser.getName());
	langUser.setName("喜洋洋");

    //新建对象插入表中,让sqlsession 有提交动作
	LangUser langUser3 = new LangUser();
	langUser3.setName("红太狼");
	langUser3.setAge(5);
	langUser3.setScore("90");
	langUserMapper.insert(langUser3);

	LangUser langUser1 = langUserMapper.selectByPrimaryKey(-1);
	logger.info("姓名:"+langUser1.getName());
	LangUser langUser2 = langUserMapper.selectByPrimaryKey(-1);
	logger.info("姓名:"+langUser2.getName());
}

分析下console 其中有写日志我删除了为了方便大家阅读:
在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值