像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提
高性能。
Mybatis 中缓存分为一级缓存,二级缓存。
一级缓存是session级别的缓存,只要sqlSession没有flush或者close,它就存在。无需配置
/** * 用户的持久层接口 * Ceate By llb on 2019/8/5 */ public interface UserMapper { /** * 根据id查询用户 * @return */ User findUserById(int id); }
<?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.llb.dao.UserMapper"> <!--useCache--> <select id="findUserById" resultType="user" parameterType="int" useCache="true"> select * from user where id = #{id} </select> </mapper>
package com.llb.test;
/**
* Ceate By llb on 2019/8/5
*/
public class UserTest {
InputStream in = null;
UserMapper mapper = null;
SqlSession sqlSession = null;
SqlSessionFactory factory = null;
/**
* 在测试方法执行前执行
* @throws IOException
*/
@Before
public void init() throws IOException {
//1.读取配置文件,生成字节流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取sqlSessionFactory对象
factory = new SqlSessionFactoryBuilder().build(in);
//3.获取sqlSession对象
sqlSession = factory.openSession();
//4.获取dao的代理对象
mapper = sqlSession.getMapper(UserMapper.class);
}
/**
* 测试方法执行后执行
* @throws IOException
*/
@After
public void destory() throws IOException {
sqlSession.commit();
//6.释放资源
sqlSession.close();
in.close();
}
/**
* 根据id查询用户,sqlSession一级缓存:
* 当调用sqlSession的修改、添加、删除,commit() ,close(),clear()等方法时,会清空缓存
*/
@Test
public void findUserById(){
User user = mapper.findUserById(41);
User user2 = mapper.findUserById(41);
System.out.println(user == user2);
}
}
测试结果:
我们虽然查询了两次,但最后只查询了一次数据库,这就是Mybatis提供给我们得一级缓存起作用。因为一级缓存的存在,导致第二次查询id为41的记录时,并没有发出sql语句从数据库中查询数据,而是从一级缓存中查询。
一级缓存是SqlSession范围的缓存,当调用SqlSession的修改、添加、删除时、commit、close等方法就会清空缓存。
第一次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,如果没有,从数据库查询用户信息。
得到用户信息,将用户信息存储到一级缓存中。
如果 sqlSession 去执行 commit 操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,缓存中有,直接从缓存中获取用户信息。
/**
* 根据id查询用户,sqlSession一级缓存:
* 当调用sqlSession的修改、添加、删除,commit() ,close(),clear()等方法时,会清空缓存
*/
@Test
public void findUserById(){
User user = mapper.findUserById(41);
//关闭sqlSession会清空缓存
sqlSession.close();
sqlSession = factory.openSession();
mapper = sqlSession.getMapper(UserMapper.class);
//直接对sqlSession进行清空
// sqlSession.clearCache();
User user2 = mapper.findUserById(41);
System.out.println(user == user2);
}
当执行sqlSession.close()后,再次获取sqlSession并查询id=41的User对象时,又重新执行了sql 语句,从数据库进行了查询操作。导致两个用户的地址不一致。
原文:https://www.cnblogs.com/liulebin/p/11342087.html