一级缓存是在SQLSession上的缓存,二级缓存是在SQLSessionFactory上的缓存,默认情况下,也就是没有任何配置的情况下,MyBatis系统会开启一级缓存,也就是SQLSession层面上的缓存,这个缓存不需要POJO对象的可序列化。即:
当一个SQLSession第一次通过SQL和参数获取对象后,他就会将其缓存起来,如果下次的SQL和参数都没有发生变化,并且缓存没有超时(关于时间,在cache的配置项里有一个flushInterval属性,默认值为null,也就是没有刷新时间,只有当执行update,delete,insert时才会刷新)或者需要声明刷新,那么他就会从缓存中读取数据,而不是通过SQL获取。即通过一个SQLSession获得映射器接口A,下次再用这个接口A来获得数据,还是一样的(需要满足上述前提条件)。
SqlSession sqlSession=null;
try {
sqlSession=SqlSessionFactoryUtils.openSqlSession();
RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
Role role = roleMapper.getRole(1);
log.info(role.getRoleName());
log.info("再取一次pojo");
Role role1=roleMapper.getRole(1);
比如上面的代码就会只执行一次sql,下一个执行就调用缓存。
另外一级缓存是在SqlSession层面的,对于不同的SqlSession对象是不能共享的。例如:
Logger log = Logger.getLogger(String.valueOf(Chapter3Main.class));
SqlSession sqlSession=null;
SqlSession sqlSession1=null;
try {
sqlSession=SqlSessionFactoryUtils.openSqlSession();
RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
Role role = roleMapper.getRole(1);
log.info(role.getRoleName());
//需要提交
sqlSession.commit();
log.info("不同SQLSession再取一次pojo");
sqlSession1 = SqlSessionFactoryUtils.openSqlSession();
RoleMapper mapper = sqlSession1.getMapper(RoleMapper.class);
Role role1=mapper.getRole(1);
//需要提交
sqlSession1.commit();
而有些时候需要在SqlSession之间共享相同的缓存,这个时候就要开启二级缓存,开启二级缓存需要对象的序列化。先要在映射文件中(RoleMapper.xm)加入:
<cache/>
,
另外由于需要对象序列化,故要让对应pojo对象实现Serializable接口。
public class Role implements Serializable {
//这个serialVersionUID值不是必须的,但是最好写上,便于版本
public static final long serialVersionUID= -8458445228523031014L;
那个UID可以在idea中自动生成。(alt+enter)。这个UID可以解决不兼容性的问题。当然不写也是可以的,就是没有考虑到不兼容的问题。
这个时候,不同的SqlSession在获取同一条的记录的时候,都是发送一次的SQL来获取数据。因为这个时候的数据是保存在SqlSessionFactory层面,可以提供给任何的SqlSession使用。只是他需要一个序列化和反序列化的过程而已。
在现实中,可以使用Redis,MongoDB 等其他缓存,如果有这么一个缓存实现类com.ssm.chapter3.cache.RedisCache,那么可以这样配置它:
<cache type="com.ssm.chapter3.cache.RedisCache">
<property name="host" value="localhost"/>
</cache>.
还有,如果一些语句如果想要自定义,比如一些查询并不想要它进行缓存,可以:
<select ``````flushCache="false" useCache="true"/>
<insert````flushCache="true"/>
注意:useCache属性是select特有的。