• Mybatis入门笔记(11)——Mybatis的缓存


    Mybatis的缓存

    缓存基本概念

    缓存是存在于内存中的临时数据

    为什么用缓存?减少和数据库的交互次数,提高执行效率。

    什么地方用缓存?

    条件 情况
    适用于缓存 经常查询并且不经常改变的,数据的正确与否对最终结果影响不大的
    不适用于缓存 经常改变的数据,数据的正确性与否对最终结果影响很大的,比如:商品的库存,银行的汇率,股市的牌价等。

    一级缓存

    一级缓存指的是Mybatis中SqlSession对象的缓存。当我们执行查询后,查询的结构会同时存入到SqlSession为我们提供的一块区域中,该区域的结构是一个Map,当我们再次查询同样的数据,Mybatis会先去SQLSession中查询是否有,有的话直接拿出来用。当SQLSession对象消失后(被flush或close),Mybatis的一级缓存也就消失了。

    下面举例说明:

    1. 编写用户持久层Dao接口;

      public interface IUserDao {
          // 根据ID查询用户
          User findUserById(Integer id);
      }
      
    2. 编写持久层映射文件;

      <?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.ben.dao.IUserDao">
          <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
          <resultMap id="userMap" type="uSer">
              <!-- 主键字段的对应 -->
              <id property="userId" column="id"></id>
              <!--非主键字段的对应-->
              <result property="userName" column="username"></result>
              <result property="userAddress" column="address"></result>
              <result property="userSex" column="sex"></result>
              <result property="userBirthday" column="birthday"></result>
          </resultMap>
      
          <!-- 查询所有 -->
          <select id="findUserById" resultMap="userMap">
              select * from user where id = #{v};
          </select>
      
      </mapper>
      

    3. 编写测试方法

      public class MybatisTest {
      
          private SqlSessionFactory factory;
          private IUserDao userdao;
          private InputStream in;
          private SqlSession session;
      
          // 作用:在测试方法前执行这个方法
          @Before
          public void setUp() throws Exception {
              //1.读取配置文件
              in = Resources.getResourceAsStream("SqlMapConfig.xml");
              //2.创建SqlSessionFactory工厂
              SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
              //3.创建SqlSession工厂对象
              factory = builder.build(in);
              //4.使用工厂生产SqlSession对象
              session = factory.openSession();
              //5.创建Dao接口的代理对象
              userdao = session.getMapper(IUserDao.class);
          }
      
          @After//在测试方法执行完成之后执行
          public void destroy() throws IOException {
              session.close();
              in.close();
          }
      
          // 根据用户ID查找用户
          @Test
          public void testFindUserById(){
              User user1 = userdao.findUserById(41);
              System.out.println(user1);
      
              session.close();
      
              //再次生产SqlSession对象
              session = factory.openSession();
              userdao = session.getMapper(IUserDao.class);
      
              User user2 = userdao.findUserById(41);
              System.out.println(user2);
      
              System.out.println(user1 == user2);
      
          }
      }
      

    ​ 当执行sqlSession.close()后,再次获取sqlSession并查询id=41的User对象时,又重新执行了sql语句,从数据

    库进行了查询操作。 结果发现,两次拿到的数据不一样。

    此外还可以通过 session.clearCache()清空一级缓存。

    // 根据用户ID查找用户
    @Test
    public void testFindUserById() {
        User user1 = userdao.findUserById(41);
        System.out.println(user1);
    
    //        session.close();
        session.clearCache();
        //再次生产SqlSession对象
        session = factory.openSession();
        userdao = session.getMapper(IUserDao.class);
    
        User user2 = userdao.findUserById(41);
        System.out.println(user2);
    
        System.out.println(user1 == user2);
    }
    

    二级缓存

    它指的是Mybatis中SQLSessionFactory对象的缓存,由同一个SQLSessionFactory对象创建的SqlSession共享其缓存。

    使用步骤:

    1. 让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)

      <!--    配置缓存-->
      <settings>
          <setting name="cacheEnabled" value="true"/>
      </settings>
      
    2. 让当前的映射文件支持二级缓存(在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.ben.dao.IUserDao">
          <cache/>
          <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
          <resultMap id="userMap" type="uSer">
              <!-- 主键字段的对应 -->
              <id property="userId" column="id"></id>
              <!--非主键字段的对应-->
              <result property="userName" column="username"></result>
              <result property="userAddress" column="address"></result>
              <result property="userSex" column="sex"></result>
              <result property="userBirthday" column="birthday"></result>
          </resultMap>
      
          <!-- 查询所有 -->
          <select id="findUserById" resultMap="userMap" useCache="true">
              select * from user where id = #{v};
          </select>
      </mapper>
      
    3. 让当前的操作支持二级缓存(在select标签中配置) useCache="true"

    编写测试类

    @Test
    public void testSecondCache() {
        SqlSession session = factory.openSession();
        IUserDao dao1 = session.getMapper(IUserDao.class);
        User user1 = dao1.findUserById(41);
        System.out.println(user1);
        //一级缓存消失
        session.close();
    //        session.clearCache();
        //再次生产SqlSession对象
        SqlSession session2 = factory.openSession();
        IUserDao dao2 = session2.getMapper(IUserDao.class);
    
        User user2 = dao2.findUserById(41);
        System.out.println(user2);
        session.close();
    
        System.out.println(user1 == user2);
    
    }
    

    经过上面的测试,我们发现执行了两次查询,并且在执行第一次查询后,我们关闭了一级缓存,再去执行第二
    次查询时,我们发现并没有对数据库发出 sql 语句,所以此时的数据就只能是来自于我们所说的二级缓存。 第二次直接从二级缓存中拿到的数据。

    二级缓存图解:二级缓存存放的内容是数据,而不是对象。

  • 相关阅读:
    iOS开发-Sqlite
    iOS开发-HTTP协议
    iOS开发
    iOS 开发小记 (八)
    iOS
    iOS开发-基础框架
    Java门面模式
    Linux常用命令
    canal使用小结
    MySQL隔离级别的测试
  • 原文地址:https://www.cnblogs.com/benjieqiang/p/11217856.html
Copyright © 2020-2023  润新知