一级缓存

HeJin大约 3 分钟数据库技术Mybatis

一级缓存也叫本地缓存:

  • 与数据库同一次会话期间查询到的数据会放在本地缓存中。
  • 以后如果需要获取相同的数据,直接从缓存中拿,没必须在去查询数据库。

一级缓存测试

相同的查询

@Test
public void test01(){

    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user1 = userMapper.getUserById8(1);
    System.out.println(user1);

    User user2 = userMapper.getUserById8(1);
    System.out.println(user2);

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

    sqlSession.close();

}

结果

Opening JDBC Connection
Created connection 1233705144.
==>  Preparing: select * from user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 狂神, 123456
<==      Total: 1
User(id=1, name=狂神, pwd=123456)
User(id=1, name=狂神, pwd=123456)
true
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4988d8b8]
Returned connection 1233705144 to pool.

Process finished with exit code 0

可以发现,在一个sqlSession中,两次相同的查询只会查一次数据库,第二次会查一级缓存。

不同的查询

@Test
public void test01(){

    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user1 = userMapper.getUserById8(1);
    System.out.println(user1);

    User user2 = userMapper.getUserById8(2);
    System.out.println(user2);

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

    sqlSession.close();

}

结果

Opening JDBC Connection
Created connection 1233705144.
==>  Preparing: select * from user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 狂神, 123456
<==      Total: 1
User(id=1, name=狂神, pwd=123456)
==>  Preparing: select * from user where id = ? 
==> Parameters: 2(Integer)
<==    Columns: id, name, pwd
<==        Row: 2, 法外狂徒张三, 333333
<==      Total: 1
User(id=2, name=法外狂徒张三, pwd=333333)
false
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4988d8b8]
Returned connection 1233705144 to pool.

Process finished with exit code 0

可以发现,由于是两次不同的查询。查了两次数据库,没有走缓存。

相同的查询中间有update

@Test
public void test02(){

    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    User user1 = userMapper.getUserById8(1);
    System.out.println(user1);

    /**
     * update信息
     */
    userMapper.updateUser8(new User(5,"小吴","555"));

    User user2 = userMapper.getUserById8(1);
    System.out.println(user2);

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

    sqlSession.close();

}

结果

Opening JDBC Connection
Created connection 1233705144.
==>  Preparing: select * from user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 狂神, 123456
<==      Total: 1
User(id=1, name=狂神, pwd=123456)
==>  Preparing: update user set name=?,pwd=? where id = ? 
==> Parameters: 小吴(String), 555(String), 5(Integer)
<==    Updates: 1
==>  Preparing: select * from user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 狂神, 123456
<==      Total: 1
User(id=1, name=狂神, pwd=123456)
false
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4988d8b8]
Returned connection 1233705144 to pool.

Process finished with exit code 0

可以发现,虽然两次查的都是1号用户。但是因为中间有更新2号用户的数据,缓存失效了。查了两次数据库。

手动清除缓存

@Test
public void test02(){

    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    User user1 = userMapper.getUserById8(1);
    System.out.println(user1);
    /**
     * 清理缓存
     */
    sqlSession.clearCache();

    User user2 = userMapper.getUserById8(1);
    System.out.println(user2);

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

    sqlSession.close();

}

结果

Opening JDBC Connection
Created connection 1233705144.
==>  Preparing: select * from user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 狂神, 123456
<==      Total: 1
User(id=1, name=狂神, pwd=123456)
==>  Preparing: select * from user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 狂神, 123456
<==      Total: 1
User(id=1, name=狂神, pwd=123456)
false
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4988d8b8]
Returned connection 1233705144 to pool.

Process finished with exit code 0

可以发现,手动清除缓存之后。相同的查询查了两次数据库。

缓存失效

  • 不同的查询SQL。
  • 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。增删改可能会改变原来的数据,所以需要刷新缓存。
  • 查询不同的mapper.xml
  • 手动清除缓存

理解

默认开启。只在一次SqlSession中有效,也就是在拿到连接和关闭连接这个区间有效。一级缓存就是一个map。

image-20201201120143643
image-20201201120143643