15-一级缓存

Posted zuiren

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了15-一级缓存相关的知识,希望对你有一定的参考价值。

一、Mybatis 中的缓存

1.什么是缓存

存在内存中的临时数据。

2.为什么使用缓存

减少与数据库交互次数,提高执行效率

3.什么样的数据能使用缓存,什么样的数据不能使用缓存

适用于缓存:

  1. 经常查询并且不经常改变。
  2. 数据的正确与否对最终结果影响不大的。

不适用于缓存:

  1. 经常改变的数据。
  2. 数据的正确与否对最终结果影响很大。
  3. 例如:商品的库存,银行的汇率,股市的牌价。

3.Mybatis 中的一级缓存和二级缓存

一级缓存:

  1. 它指的是 Mybatis 中 SqlSession 对象的缓存。
  2. 当我们执行查询之后,查询的结果会同时存入到 SqlSession 为我们提供一块区域中。
  3. 该区域的结构时一个 Map 。当我们再次查询同样的数据,mybatis 会先去 sqlsession 中查询是否有,有的话直接拿出来用。
  4. 当 SqlSession 对象消失时,mybatis 的一级缓存也就消失了。

二、一级缓存

一级缓存分析

一级缓存是 sqlsession 范围的缓,当调用 sqlsession 的修改、添加、删除、commit()、close()等方法时,就会清空一级缓存

1.一级缓存测试

Ⅰ测试类代码

    /**
     * 一级缓存
     */
    @Test
    public void testFirstLevelCache()
        User user1=userDao.findById(1);
        System.out.println(user1);
        User user2=userDao.findById(1);
        System.out.println(user2);
        System.out.println(user1==user2);
    

Ⅱ输出结果

Opening JDBC Connection
[DEBUG] 2019-08-16 10:37:32,206 method:org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:424)
Created connection 11902257.
[DEBUG] 2019-08-16 10:37:32,209 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==>  Preparing: select *from user where id=? 
[DEBUG] 2019-08-16 10:37:32,233 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==> Parameters: 1(Integer)
[DEBUG] 2019-08-16 10:37:32,254 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
<==      Total: 1
domain.User@19dc67c2
[DEBUG] 2019-08-16 10:37:32,254 method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.close(JdbcTransaction.java:90)
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@b59d31]
[DEBUG] 2019-08-16 10:37:32,255 method:org.apache.ibatis.datasource.pooled.PooledDataSource.pushConnection(PooledDataSource.java:381)
Returned connection 11902257 to pool.
[DEBUG] 2019-08-16 10:37:32,255 method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.openConnection(JdbcTransaction.java:136)
Opening JDBC Connection
[DEBUG] 2019-08-16 10:37:32,255 method:org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:416)
Checked out connection 11902257 from pool.
[DEBUG] 2019-08-16 10:37:32,256 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==>  Preparing: select *from user where id=? 
[DEBUG] 2019-08-16 10:37:32,256 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==> Parameters: 1(Integer)
[DEBUG] 2019-08-16 10:37:32,257 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
<==      Total: 1
domain.User@62bd765
false

可以看到上面的两个对象是同一个,并且返回是 true

而且他只发起了一次查询,第一次查询,第二次是从缓存中取出

如果 sqlsession 关闭则一级缓存关闭

2.关闭一级缓存

两种方法有所区别:

第一种方法是关闭 sqlsession ,重新建立一个

第二种是不关闭 sqlsession ,只清除缓存

Ⅰ第一种方法:

    /**
     * 关闭一级缓存
     */
    @Test
    public void testFirstLevelCache2()
        User user1=userDao.findById(1);
        System.out.println(user1);
        sqlSession.close();
        //再次获取 sqlsession
       sqlSession= factory.openSession(true);
        userDao=sqlSession.getMapper(IUserDao.class);

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

输出日志:

Opening JDBC Connection
[DEBUG] 2019-08-16 10:37:32,255 method:org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:416)
Checked out connection 11902257 from pool.
[DEBUG] 2019-08-16 10:37:32,256 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==>  Preparing: select *from user where id=? 
[DEBUG] 2019-08-16 10:37:32,256 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==> Parameters: 1(Integer)
[DEBUG] 2019-08-16 10:37:32,257 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
<==      Total: 1
domain.User@62bd765
false

Ⅱ第二种方法:

    @Test
    public void testFirstLevelCache2()
        User user1=userDao.findById(1);
        System.out.println(user1);
        
        sqlSession.clearCache();
        userDao=sqlSession.getMapper(IUserDao.class);

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

输出日志:

Opening JDBC Connection
[DEBUG] 2019-08-16 10:41:08,333 method:org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:424)
Created connection 11902257.
[DEBUG] 2019-08-16 10:41:08,336 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==>  Preparing: select *from user where id=? 
[DEBUG] 2019-08-16 10:41:08,365 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==> Parameters: 1(Integer)
[DEBUG] 2019-08-16 10:41:08,386 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
<==      Total: 1
domain.User@19dc67c2
[DEBUG] 2019-08-16 10:41:08,387 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==>  Preparing: select *from user where id=? 
[DEBUG] 2019-08-16 10:41:08,389 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==> Parameters: 1(Integer)
[DEBUG] 2019-08-16 10:41:08,392 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
<==      Total: 1
domain.User@62bd765
false

2.在两个相同查询中间进行增、删、改

一级缓存分析

一级缓存是 sqlsession 范围的缓,当调用 sqlsession 的修改、添加、删除、commit()、close()等方法时,就会清空一级缓存

Ⅰ改代码

    /**
     * 测试缓存的同步
     */
    @Test
    public void testClearCache()
        //1.根据 id 查询用户
        User user1=userDao.findById(1);
        System.out.println(user1);

        //2.跟新用户信息
        user1.setUsername("update user");
        user1.setAddress("北京市海淀区");
        userDao.updateUser(user1);

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

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

输出日志:

Opening JDBC Connection
[DEBUG] 2019-08-16 10:56:30,917 method:org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:424)
Created connection 11902257.
[DEBUG] 2019-08-16 10:56:30,922 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==>  Preparing: select *from user where id=? 
[DEBUG] 2019-08-16 10:56:30,946 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==> Parameters: 1(Integer)
[DEBUG] 2019-08-16 10:56:30,962 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
<==      Total: 1
domain.User@19dc67c2
[DEBUG] 2019-08-16 10:56:30,964 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==>  Preparing: update user set username=?,address=? where id=? 
[DEBUG] 2019-08-16 10:56:30,964 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==> Parameters: update user(String), 北京市海淀区(String), 1(Integer)
[DEBUG] 2019-08-16 10:56:30,982 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
<==    Updates: 1
[DEBUG] 2019-08-16 10:56:30,983 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==>  Preparing: select *from user where id=? 
[DEBUG] 2019-08-16 10:56:30,983 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
==> Parameters: 1(Integer)
[DEBUG] 2019-08-16 10:56:30,984 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143)
<==      Total: 1
domain.User@78a2da20
false

以上是关于15-一级缓存的主要内容,如果未能解决你的问题,请参考以下文章

一级数据缓存,一级指令缓存和二级缓存有啥区别?

什么是一级缓存,什么是二级缓存?

一级缓存和二级缓存有啥区别

谁给我解释一下一级缓存和二级缓存啊~

什么是缓存?一级缓存?二级缓存?

MyBatis缓存专题-一文彻底搞懂MyBatis一级缓存