首先回顾一下(一)的内容
重用执行器 Reuse Executor
Q:一个SqlSession执行了selectList和selectOne,两个的sql语句都相同,是否可以命中Statement的缓存?
![fd45a6670ecb00ed837499a3424596f2.png](https://img-blog.csdnimg.cn/img_convert/fd45a6670ecb00ed837499a3424596f2.png)
A:可以命中缓存
所命中的缓存是JDBC中的ReuseStatement的PrepareStatement的缓存,不是一级缓存,只要最终的SQL语句一样就会命中Statement
UserMapper:
@CacheNamespace
public interface UserMapper {
//两个SQL一样
@Select({
" select * from users where id=#{1}"})
User selectByid(Integer id);
@Select({
" select * from users where id=#{1}"})
User selectByid3(Integer id);
}
@Test
public void sessionByReuseTest(){
SqlSession sqlSession = factory.openSession(ExecutorType.REUSE, true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//两个select对应两个不同的 MappedStatement 映射,会不会采用一个预处理器Statement?
//(JDBC的Statement)
mapper.selectByid(10);
mapper.selectByid3(10);
}
题目所说的Statement指的是JDBC的Statement
![bc0c92094ce984f60bc83e1de7482836.png](https://img-blog.csdnimg.cn/img_convert/bc0c92094ce984f60bc83e1de7482836.png)
可以看到只引入了一次预编译
如果说两个SQL不一样
@CacheNamespace
public interface UserMapper {
//两个SQL一样
@Select({
" select * from users where id=#{1}"})
User selectByid(Integer id);
@Select({
" select * from users where id=#{1} and 1=1"})
User selectByid3(Integer id);
}
//重用执行器
@Test
public void sessionByReuseTest(){
SqlSession sqlSession = factory.openSession(ExecutorType.REUSE, true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//两个select对应两个不同的 MapperStatement,不会会采用一个预处理器Statement?
mapper.selectByid(10);
mapper.selectByid3(10);
}
![e872572b0cdebcbc2cbf3327ce375411.png](https://img-blog.csdnimg.cn/img_convert/e872572b0cdebcbc2cbf3327ce375411.png)
可以看到引入了两次预编译
结论:只要是SQL语句相同,就会重复利用Statement,不论是doQuery还是doUpdate最终都还是会重复的使用Statement
查看源代码可以看到:
![bd6050e5a872205dd864deae22ff1495.png](https://img-blog.csdnimg.cn/img_convert/bd6050e5a872205dd864deae22ff1495.png)
String是他的SQL语句
Statement就是他缓存的JDBC的Statement
查看doQuery源码
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this.wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
//预编译SQL语句
Statement stmt = this.prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);
}
在预编译过程prepareStatement中(对应jdbc中的prepareStatement)
![b7c1e4ea82ea126ac8165b40c5dbfe5f.png](https://img-blog.csdnimg.cn/img_convert/b7c1e4ea82ea126ac8165b40c5dbfe5f.png)
如果没有就通过StatementHandler构建一个新的Statement,之后put进缓存中
总结:在会话期间内,所有相同的SQL语句会采用同样的Statement,只有会话结束之后Statement才会一起关闭
批处理执行器
![bcc4ae07b0967f98bab72a8ab626a507.png](https://img-blog.csdnimg.cn/img_convert/bcc4ae07b0967f98bab72a8ab626a507.png)
会话把所有的请求都发往Batch Executor,而Batch Executor会把所有的SQL语句保存起来到Statement集合中(缓存),等到flushStatement时一起进行处理(所有的增删改同时进行处理,不管StatementID是否一样),但是不一定都采用同一个Statement
@Test
public void sessionBatchTest(){
SqlSession sqlSession = factory.openSession(ExecutorType.BATCH,true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.setName(10,"道友友益永存");
mapper.addUser(Mock.newUser());
sqlSession.flushStatements();
}
Q:是否会使用同一个JDBC Statement?
A:不是同一个Statement
Q:set和add操作是一起提交的么?
A:是一起提交的
验证:此时断点查看
![7097c3cfc0d35ebaf808eb37e6e6013f.png](https://img-blog.csdnimg.cn/img_convert/7097c3cfc0d35ebaf808eb37e6e6013f.png)
此时数据还没有提交
![593bf32b7a546ec24bd9c98dd983678a.png](https://img-blog.csdnimg.cn/img_convert/593bf32b7a546ec24bd9c98dd983678a.png)
继续执行后查看数据库
![be067e0f5659d50a3cd3d8d430a4f64d.png](https://img-blog.csdnimg.cn/img_convert/be067e0f5659d50a3cd3d8d430a4f64d.png)
在我们调用setName和