SSM学习之路——Mybatis第四天_一级缓存和二级缓存

在我们查询的时候,有些不是很必要的信息,我们可以利用缓存是没有问题的,比如库存这种,如果每个商品的库存的实时刷新显示在页面上的话,那得有多大的开销,数据库查询量是很大的,真正用户提交订单的时候,我们再去查询数据库,可以减少很多开销。
哪些不能用缓存呢,就是比如股票系统啊,实时交易的这种,必须不能使用缓存,这需要对缓存有一定的了解。

一、一级缓存相关

(1)新建IUserDao接口

在这里插入图片描述

(2)新建User实体类

写入对应数据库的相应字段,并生成set&get方法(这里不再生成tostring,因为我们此刻不需要关心用户的数据)
在这里插入图片描述

(3)编写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="com.itheima.dao.IUserDao">
    <select id="findById" resultType="user" parameterType="int">
        select * from user where id=#{id}
    </select>

</mapper>

(4)编写测试类

package com.itheima.test;

import com.itheima.dao.IUserDao;
import com.itheima.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class testCacheLevel1 {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    IUserDao userDao;
    @Before
    public void init() throws IOException {
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        session = factory.openSession();
        userDao = session.getMapper(IUserDao.class);
    }
    @After
    public void destroy () throws IOException {
        session.commit();
        in.close();
    }
    @Test
    public void testLevel1Cache(){
        User user1 = userDao.findById(76);
        System.out.println(user1);

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

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

这里我们查询两次,由于我们是存在缓存的,虽然我们写了两条查询语句,但是这里视为在一次操作内查询两次,所以session还未进行事务提交(session.commit()),由于在一次查询中已经将user1存入缓存,所以在第二次发起同一个id的查询的时候,直接将user1的对象返回给user2,而不进行数据库的查询,如下图运行结果:
在这里插入图片描述
由此证明一级缓存是存在的。

上面提到,由于我们这是在一次session创建到session.commit()之间的时间内,查询两次,所以可以存入缓存,那么如果是开启两次session,会不会还有缓存呢?
我们对上面的test方法进行如下修改:
在这里插入图片描述
我们在一次查询之后关闭了此次会话,又在让factory重新生成了一个新的会话,以及新的映射,再进行同样的第二次查询。
在这里插入图片描述
可以看到,进行了两次查询,并且对象不同。#

(5)触发清空一级缓存的情况

如果 sqlSession 去执行 commit 操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存(一级缓存为Session级别的),这样 做的目的为了让缓存中存储的是最新的信息,避免脏读。

如:
在这里插入图片描述
运行结果为:
在这里插入图片描述

二、二级缓存

上面说了一级缓存是SqlSession级别的
这里说的二级缓存为SqlSessionFactory级别的,即由一个SqlSessionFactory open出来的SqlSession对象,都共享这些缓存

接口,实体类和上述【一级缓存】相同,不再阐述

修改测试类

这里我们用同一个工厂实例,创建两个不同的SqlSession,来看区别

package com.itheima.test;

import com.itheima.dao.IUserDao;
import com.itheima.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

public class SecondLevelCache {
    private InputStream in;
    private SqlSessionFactory factory;
    IUserDao userDao;
    @Before
    public void init() throws IOException {
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
    }
    @After
    public void destroy () throws IOException {
        in.close();
    }
    @Test
    public void testLevel1Cache(){
        SqlSession session1 = factory.openSession();
        IUserDao userDao1 = session1.getMapper(IUserDao.class);
        User user1 = userDao.findById(76);
        System.out.println(user1);
        session1.close();


        SqlSession session2 = factory.openSession();
        IUserDao userDao2 = session2.getMapper(IUserDao.class);
        User user2 = userDao2.findById(76);
        System.out.println(user2);
        session2.close();

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

运行:执行了两次,你咋骗人捏!
在这里插入图片描述
:二级缓存并不是默认的,而是要手动设置,使用二级缓存需要的配置如下:

前置工作:
1、让Mybatis框架支持二级缓存(SqlMapConfig.xml)

btw:这个默认就是true,不设置也罢
在这里插入图片描述

2、让当前映射文件支持二级缓存(IUserDao.xml)
3、让当前操作支持二级缓存(select标签)

在这里插入图片描述

再进行测试
在这里插入图片描述
只查了一次,但是为啥这长得一毛一样,但是对象不是同一个对象,还换了个对象呢!

因为二级缓存,它是把对象的数据存入了缓存,例如
{“id”:76,“username”:“xxxx”,………………},第二次查询的时候只是把数据封装起来赋值给user2这个对象,所以两个对象并不是同一个引用。

缓存相关到此结束!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值