一级缓存的作用域是Executor,实际就是SqlSession,默认开启并且无法关闭,
查询的时候会先判断SqlSession是否缓存存在,如果存在直接走缓存,如果不存在则走数据库
如下 *** 作默认会走缓存:SqlSession sqlSession1 = factory.openSession(true);
SqlSession sqlSession2 = factory.openSession(true);
StudentMapper studentMapper = sqlSession1.getMapper(StudentMapper.class);
StudentMapper studentMapper2 = sqlSession2.getMapper(StudentMapper.class); System.out.println('studentMapper读取数据: ' + studentMapper.getStudentById(1)); System.out.println('studentMapper读取数据: ' + studentMapper.getStudentById(1)); System.out.println('studentMapper2更新了' + studentMapper2.updateStudentName('小岑',1)
跟spring集成的情况下 *** 作:
如上 *** 作会发现第二次查询并没有走索引,根据上面的一级缓存作用范围是sqlsession,如果不生效那说明这两次查询并没有使用同一个sqlsession,我们看看代码,发现跟spring集成之后,sqlSession对象使用的是
我们在往下看看SqlSessionTemplate
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required"); notNull(executorType, "Property 'executorType' is required"); this.sqlSessionFactory = sqlSessionFactory; this.executorType = executorType; this.exceptionTranslator = exceptionTranslator; this.sqlSessionProxy = (SqlSession) newProxyInstance( SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSession.class }, new SqlSessionInterceptor()); }
SqlSessionTemplate的private final SqlSession sqlSessionProxy;使用了一个代理对象
看看生成代理对象的代码
在使用sqlsessiontemplate做数据库 *** 作,都会走到这个代码方法里,咱们接着看这里的ggetSqlSession 方法
除非是当前的会话是有事务的,会复用sqlSession,否则是创建新的sqlSession对象
那上面的问题来看就比较清晰了,如果跟spring集成之后如果当前会话没有事务,同样的查询语句并不会命中一级索引,如果会话是有事务的是可以命中一级缓存的
二级缓存
二级缓存的作用域MappedStatement,也就是一个Mapper.xml文件,二级缓存默认是开启的,配置方式为mapperconfig里
如果具体的mapper.xml文件需要使用缓存,需要在xml文件里使用了< cache/>、< cacheRef/>标签时创建,并且会按 NameSpace 为维度,为各个 MapperStatement 传入它所属的 Namespace 的二级缓存对象。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)