MyBatis 緩存——Mybatis 一級緩存、Mybatis 二級緩存

像大多數的持久化框架一樣,Mybatis 也提供了緩存策略,通過緩存策略來減少數據庫的查詢次數,從而提高性能

Mybatis 中緩存分爲一級緩存,二級緩存
在這裏插入圖片描述

Mybatis 一級緩存

一級緩存是 SqlSession 級別的緩存,只要 SqlSession 沒有 flush 或 close,它就存在。

證明一級緩存的存在

新建數據庫映射實體類 User.java

package cn.lemon.domain;

import java.io.Serializable;
import java.util.Date;

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

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

新建持久層接口 IUserDao.java

package cn.lemon.dao;

import cn.lemon.domain.User;

public interface IUserDao {
    User findById(Integer userId);
}

新建配置文件 SqlMapConfig.xml 和 jdbc.properties

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <properties resource="jdbc.properties"/>
    <typeAliases>
        <package name="cn.lemon.domain"/>
    </typeAliases>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="cn.lemon.dao"/>
    </mappers>
</configuration>
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///db_mybatis
jdbc.username=root
jdbc.password=lemon

新建接口映射文件 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="cn.lemon.dao.IUserDao">
    <select id="findById" parameterType="int" resultType="user">
        select * from user where id = #{id}
    </select>
</mapper>

測試類

package cn.lemon.dao;

import cn.lemon.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.Test;

import java.io.InputStream;

public class IUserDaoTest {
    private InputStream inputStream;
    private SqlSessionFactory sqlSessionFactory;
    private SqlSession sqlSession;
    private IUserDao iUserDao;

    @Test
    public void findById() throws Exception{
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        sqlSession = sqlSessionFactory.openSession(true);
        iUserDao = sqlSession.getMapper(IUserDao.class);

        /*第一次查詢*/
        User user1 = iUserDao.findById(58);
        System.out.println("第一次查詢:" + user1);
        System.out.println("-------------------------------------------");

        /*第二次查詢*/
        User user2 = iUserDao.findById(58);
        System.out.println("第二次查詢:" + user2);

        sqlSession.close();
        inputStream.close();
    }
}

運行結果:
在這裏插入圖片描述
關閉緩存,或者使用sqlSession.clearCache 清除緩存,或者對查詢的這條語句執行修改,就會出現兩次查詢
在這裏插入圖片描述

Mybatis 二級緩存 (重要)

二級緩存的特點

  • 二級緩存是 mapper 映射級別的緩存
  • 多個 SqlSession 去操作同一個 Mapper 映射的 sql 語句
  • 多個SqlSession 可以共用二級緩存
  • 二級緩存是跨 SqlSession 的。
    在這裏插入圖片描述

二級緩存的配置

第一步:在 SqlMapConfig.xml 文件開啓二級緩存

    <settings>
        <!-- 
            開啓二級緩存的支持
            因爲 cacheEnabled 的取值默認就爲 true,所以這一步可以省略不配置。爲 true 代表開啓二級緩存;爲 false 代表不開啓二級緩存
         -->
        <setting name="cacheEnabled" value="true"/>
    </settings>

第二步:在 IUserDao.xml 中,配置相關的 Mapper 映射文件

    <!--
        開啓二級緩存的支持
        <cache>標籤表示當前這個 mapper 映射將使用二級緩存,區分的標準就看 mapper 的 namespace
    -->
    <cache></cache>

第三步:在 IUserDao.xml 中,配置 statement 上面的 useCache 屬性
在這裏插入圖片描述
第四步:測試類

package cn.lemon.dao;

import cn.lemon.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.Test;

import java.io.InputStream;

public class IUserDaoTest {

    @Test
    public void findById() throws Exception {
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        /*第一次查詢*/
        SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
        IUserDao iUserDao1 = sqlSession1.getMapper(IUserDao.class);
        User user1 = iUserDao1.findById(58);
        System.out.println("第一次查詢:" + user1);
        System.out.println("-------------------------------------------");
        sqlSession1.close();//關閉資源

        /*第二次查詢*/
        SqlSession sqlSession2 = sqlSessionFactory.openSession(true);//重新開啓
        IUserDao iUserDao2 = sqlSession2.getMapper(IUserDao.class);
        User user2 = iUserDao2.findById(58);
        System.out.println("第二次查詢:" + user2);
        System.out.println("-------------------------------------------");
        sqlSession2.close();

        /*第三次查詢*/
        SqlSession sqlSession3 = sqlSessionFactory.openSession(true);//重新開啓
        IUserDao iUserDao3 = sqlSession3.getMapper(IUserDao.class);
        User user3 = iUserDao3.findById(58);
        System.out.println("第三次查詢:" + user3);
        System.out.println("-------------------------------------------");
        sqlSession3.close();

        inputStream.close();
    }
}

運行結果:
在這裏插入圖片描述
特別提醒:

  • 二級緩存要實現序列化接口,也就是 implements Serializable
  • 二級緩存要在同一個命名空間下,不用的命名空間有不同的緩存,如上面的例子 namespace="cn.lemon.dao.IUserDao"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章