Mybatis中的以及缓存和二级缓存
一级缓存:
它指的是Mybatis中SqlSession对象的缓存
当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供的一块区域中
该区域的结构是一个Map。
当我们再次查询同样的数据,mybatis会先去SqLSession中查询是否有,有的话直接拿来用
当SqlSession对象消失时,mybatis的一级缓存也消失
二级缓存:
它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存
使用步骤:
1.让mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
2.让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
3.让当前的操作支持二级缓存(在select标签中配置)
注意
一级缓存是把数据存到sqlsession对象中的map里,二级缓存是根据sqlsessionfactory先创建sqlsession对象,然后把缓存的中的数据填充到sqlsession中
二级缓存是以序列化形式存储的,如果domain对象不支持序列化就会包NotSerializableExecption
这里我们创建一个user实体类(set和get就不展示了)
public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
}
写上它的Dao接口
/*
用户的持久层接口
*/
public interface IUserDao {
/**
* 查询所有用户,同时获取到用户下所有账户的信息
* @return
*/
List<User> findAll();
//根据id查询用户信息
User findById(Integer userid);
//更新用户信息
void updateUser(User user);
}
编写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">
<!-- 开启user支持二级缓存 -->
<cache/>
<!--查询所有-->
<select id="findAll" resultType="com.itheima.domain.User">
select u.*, a.id as aid, uid, money from user u left outer join account a on u.id = a.uid;
</select>
<!--根据id查询用户-->
<select id="findById" parameterType="int" resultType="com.itheima.domain.User" useCache="true">
select * from user where id = #{uid} /*{}内为占位符,可随意写*/
</select>
<!-- 更新用户信息 -->
<update id="updateUser" parameterType="com.itheima.domain.User">
update user set username = #{username},address = #{address} where id = #{id}
</update>
</mapper>
编写测试类,测试一级缓存
//6.释放资源
sqlSession.close();
in.close();
}
/**
* 测试一级缓存
*/
@Test
public void testFirstLevelCache() {
User user1 = userDao.findById(41);
System.out.println(user1);
sqlSession.close();
// 再次获取SqlSession对象
sqlSession = factory.openSession();
userDao = sqlSession.getMapper(IUserDao.class);
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1 == user2); // false
}
/**
* 测试缓存的同步
*/
@Test
public void testClearCache() {
//1.根据id查询用户
User user1 = userDao.findById(41);
System.out.println(user1);
//2.更新用户信息
user1.setUsername("update user clear cache");
user1.setAddress("北京市海淀区");
userDao.updateUser(user1);
//3.再次查询id为41的用户
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1 == user2);
}
编写第二个测试类,测试二级缓存
public class SecondLevelCacheTest {
private InputStream in;
private SqlSessionFactory factory;
@Before//用于在测试方法之前执行
public void init() throws IOException {
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取SqlSessionFactory对象
factory = new SqlSessionFactoryBuilder().build(in);
}
@After//用于在测试方法之后执行
public void destroy() throws IOException {
in.close();
}
/**
* 测试二级缓存
*/
@Test
public void testFirstLevelCache() {
SqlSession sqlSession1 = factory.openSession();
IUserDao dao1 = sqlSession1.getMapper(IUserDao.class);
User user1 = dao1.findById(41);
System.out.println(user1);
sqlSession1.close(); //一级缓存消失
SqlSession sqlSession2 = factory.openSession();
IUserDao dao2 = sqlSession2.getMapper(IUserDao.class);
User user2 = dao1.findById(41);
System.out.println(user2);
sqlSession2.close();
System.out.println(user1 == user2); // false
}