readOnly属性:只读 (true/false)
true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此返回的这些缓存对象自己没事不要去修改。一旦修改,就会影响下一个相同查询条件的查询结果。这提供了很重要的性能优势。
false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这些对象可以随意修改,不会影响后续相同查询条件的结果。这会慢一些,但是安全,因此默认是false。
实验一、
1.把readOnly设置为默认状态:false

2.为了确保实验的准确性,我进行了三次查询。
第一次,查询之后返回了数据库中的数据,映射为实例对象,我们这时候提交一下(提交之后缓存就不在一级缓存了,就被读写到了二级缓存)
第二次,查询之后,返回缓存对象的拷贝,我们把返回的拷贝对象(List集合)清空。
第三次,查询之后,返回缓存对象的拷贝,我们输出一下发现集合是空
@Test
public void getEmpByConditionTest(){
SqlSession session1 = SqlSessionUtils.getSqlSession();
SqlSession session2 = SqlSessionUtils.getSqlSession();
//第一次查询,无缓存,查询的数据库
DynasicSQLMapper dynasicSQLMapper = session1.getMapper(DynasicSQLMapper.class);
Emp emp = new Emp(null,"zhangsan",12,"男",null);
final List<Emp> list = dynasicSQLMapper.getEmpByCondition(emp);
System.out.println(list);
System.out.println("=========================");
//提交到二级缓存
session1.commit();
//第二次查询,在二级缓存
DynasicSQLMapper dynasicSQLMapper2 = session2.getMapper(DynasicSQLMapper.class);
List<Emp> list2 = dynasicSQLMapper.getEmpByCondition(emp);
//清空返回的缓存对象
list2.clear();
System.out.println(list2);
System.out.println("=========================");
//第三次查询,在二级缓存中查询
DynasicSQLMapper dynasicSQLMapper3 = session2.getMapper(DynasicSQLMapper.class);
List<Emp> list3 = dynasicSQLMapper.getEmpByCondition(emp);
System.out.println(list3);
}
3.从结果来看,第一次查询缓存中没找到,查的是数据库。第二次查询缓存的命中率为0.5,说明查到了缓存,第三次也一样,查到了缓存。

实验二、
1.把readOnly设置为:true
2.查询代码不变
3.从结果来看,第一次查询,缓存命中率为0,说明缓存中没找到,查的是数据库。第二次查询缓存的命中率为0.5,说明查到了缓存,第三次也一样,查到了缓存。

总结:
当readOnly为false时,修改返回的缓存对象(的拷贝),不会修改缓存中的数据。
当readOnly为true时,修改返回的缓存对象(的相同实例),会修改缓存中的数据,影响下一次相同查询条件的查询结果。
148



被折叠的 条评论
为什么被折叠?



