Java框架_Mybatis_day09_缓存

14 篇文章 0 订阅
11 篇文章 0 订阅

目录

十三、Mybatis 缓存

13.1 简介

13.2 一级缓存

13.2.1 一级缓存的简介

13.2.2 测试一级缓存

13.2.3 一级缓存的改进测试

13.3 二级缓存

13.3.1 简介

13.3.2 二级缓存的开启与关闭

13.3.3 二级缓存的测试

13.3.4 二级缓存的应用场景


十三、Mybatis 缓存

13.1 简介

像大多数的持久化框架一样,Mybatis也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。

 

Mybatis中缓存分为一级缓存,二级缓存

      一级缓存:是SqlSession级别的缓存(线程级别的缓存)

      二级缓存:是SqlSessionFactory级别的缓存(进程级别的缓存)

      一个SqlSessionFactory存在多个SqlSession。

13.2 一级缓存

13.2.1 一级缓存的简介

一级缓存指的是Mybatis中SqlSession对象的缓存。

         当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。

         该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有的话直接拿出来用,如果没有再查询数据库。

         当SqlSession对象消失时,mybatis的一级缓存也就消失了。

13.2.2 测试一级缓存

User.java

public class User {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    // set、get方法
}

UserDao.java

public User findById(Integer id);

UserDao.xml

    <select id="findById" resultType="user" parameterType="int">
        select * from user where id = #{id}
    </select>

MybatisTest.java

    @Test
    public void findById(){
        User user1 = userDao.findById(48);
        System.out.println(user1);
        User user2 = userDao.findById(48);
        System.out.println(user2);
        System.out.println(user1 == user2);
    }

       在测试类中,我们在一个sqlSession中调用了两次 findById() 方法,并将它们的地址输出(这时要把User类中的toString方法去掉),来比较它们是否为一个对象,也意味着sqlSession对象是否对查询结果进行了存储。

结果显示:

      通过结果,我们可以清楚地看到两个对象的地址完全相同,并且查询操作只进行了一次。

13.2.3 一级缓存的改进测试

       这里我们在测试方法中手动关闭sqlSession,然后新建一个sqlSession来第二次调用查询方法,并且进行地址值的比较,来进一步确定sqlSession是一级缓存的载体。

MybatisTest.java

    @Test
    public void findById(){
        User user1 = userDao.findById(48);
        System.out.println(user1);
        sqlSession.close();
        sqlSession = sqlSessionFactory.openSession();
        userDao = sqlSession.getMapper(UserDao.class);
        User user2 = userDao.findById(48);
        System.out.println(user2);
        System.out.println(user1 == user2);
    }

结果显示:

       结果显而易见,在我们新建了一个sqlSession后,两次调用方法返回的 User 对象是两个不同的对象,由此证明了一级缓存就是sqlSession对象的缓存。

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

13.3 二级缓存

13.3.1 简介

       二级缓存指的是Mybatis中SqlSessionFactory对象的级别缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。

二级缓存的使用步骤:

  1. ​ 让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
  2. ​ 让当前的映射文件支持二级缓存(在UserDao.xml中配置)
  3. 让当前的操作支持二级缓存(在select标签中配置)

 

13.3.2 二级缓存的开启与关闭

第一步:在 sqlMapConfig.xml 文件中开启二级缓存(cacheEnabled)

       cacheEnabled 的取值默认就为true,所以这一步可以省略不配置。为true 代表开启二级缓存; 为false 代表不开启二级缓存 。

<!--全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存。-->
<setting name="cacheEnabled" value="true"></setting>

第二步:配置UserDao.xml中相关的Mapper 映射文件 (cache)

       <cache>标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看mapper 的namespace 值。

<mapper namespace="com.cpz.dao.UserDao">
    <cache/>
</mapper>

第三步:配置UserDao.xml中statement 上面的useCache 属性 (在select标签中配置)

       将 UserDao.xml 映射文件中的<select>标签中设置useCache=”true”代表当前这个 statement 要使用二级缓存,如果不使用二级缓存可以设置为false。

<select id="findById" resultType="user" parameterType="int" useCache="true">
    select * from user where id = #{uid}
</select>

注意:针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存。

13.3.3 二级缓存的测试

MybatisTest.java

package com.cpz.test;

import com.cpz.dao.UserDao;
import com.cpz.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 MybatisTest {

    InputStream is;
    SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws IOException {
        is = Resources.getResourceAsStream("sqlMapConfig.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
    }

    @After
    public void destroy() throws IOException {
        is.close();
    }

    @Test
    public void findById(){
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        UserDao userDao1 = sqlSession1.getMapper(UserDao.class);
        User user1 = userDao1.findById(48);
        System.out.println(user1);
        sqlSession1.close(); // 一级缓存没有了

        //  重新使用同一个sqlSessionFactory创建Session
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        UserDao userDao2 = sqlSession2.getMapper(UserDao.class);
        User user2 = userDao2.findById(48);
        System.out.println(user2);
        System.out.println(user1 == user2);
        sqlSession2.close();
    }
}

       这里我们使用同一个sqlSessionFactory工厂创建了两个不同的sqlSession对象,并分别用他们创建了userDao对象,调用了查询方法。

结果显示:

       由图可知,查询语句只执行了一次,表示二级缓存确实发挥了作用,但两个对象的地址值不同,表明二级缓存中存放的是对象的散装数据,每次查询的时候需要重新封装实体对象

13.3.4 二级缓存的应用场景

适应放置到二级缓存的数据:经常不会发生变化的数据,例如地区编码

不适合放置到二级缓存的数据:经常变化的数据,财务数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值