mybatis执行器1
sqlsession详细内容可参见 https://www.cnblogs.com/jian0110/p/9452592.html
mybatis执行过程:
一个SqlSession只能一个线程使用,所以不是线程安全的,一个线程使用完必须关闭。一个sqlsession可以执行多个sql语句。
sqlSession只提供sql会话,不会处理具体的请求。由执行器excutor来处理。
excutor也不能跨线程使用,只有查询和更新功能;excutor也不和数据库做交互,最终由statementhandle和数据库直接交互。
statementhandle对应JDBC中的statement/prestatement,callablestatement
创建sqlsession之后就对应创建了一个事务。一般来说不由mybatis来处理事务,由spring来直接处理事务。
batch和reuse都可以重用预处理器,但是reuse是重用一次预处理器,设置一次值,发送一次数据库。batch可以重用一次预处理器,多次设值,发送一次数据库。batch不能查询,只能增删改。
batch没有缓存。
reuseexcutor持有一个缓存,(只要sql语句相同就能命中statement)sql语句和对应的statement,找到对应的statement的后直接和jdbc数据库交互。
baseexcutor来实现一级缓存。有两个抽象方法,query和upfate。。doquery都在具体执行器中实现。(simple、reuse、batch)
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(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);//获取statement处理器。如preparestament
Statement stmt = prepareStatement(handler, ms.getStatementLog());//编译statement,设置staemnt值
return handler.query(stmt, resultHandler);//执行查询
}
二级缓存采用装饰者模式,其中持有baseexcutor,也就是装饰了baseexcutor。采用装饰者模式不采用纵向继承的方式是因为,继承的话,又需要添加抽象方法,需要具体的执行器(simple、reuse、batch)来实现。
代码会变的很复杂。装饰者模式,只需要持有baseexcutor,给他的抽象方法添加装饰代码,就可以完成缓存。
也就是用户使用时,只需要使用二级缓存,二级缓存相关业务执行完成后,执行baseexcutor的代码即可。
sqlsession中的select方法:
参数:
String:查询的statementid
Object:查询的参数
ResultHandle:结果集自定义
RowBounds:分页用的,查询多少行
重载这么多的方法方便调用。这种设计模式是门面模式。
代码分析:
@Test
public void sessionTest(){
SqlSession sqlSession = factory.openSession(ExecutorType.REUSE,true);
// 降低调用复杂性 门面模式 屏蔽了底层调用的复杂用 统一对接sqlSession
List<Object> list = sqlSession.selectList("org.coderead.mybatis.UserMapper.selectByid", 10); System.out.println(list.get(0)); }
1、进入opensession():
@Override public SqlSession openSession(ExecutorType execType, boolean autoCommit) { return openSessionFromDataSource(execType, null, autoCommit); }
2、openSessionFromDataSource
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { final Environment environment = configuration.getEnvironment(); final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);//事务工厂 final Executor executor = configuration.newExecutor(tx, execType);//根据执行器类型创建执行器。(执行器类型是配置的,所以需要从configuratuion获取) return new DefaultSqlSession(configuration, executor, autoCommit);//返回sqlsession } catch (Exception e) { closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); }
3、selectList
@Override public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { try { MappedStatement ms = configuration.getMappedStatement(statement);//MappedStatement类位于mybatis包的org.apache.ibatis.mapping目录下,
//是一个final类型也就是说实例化之后就不允许改变MappedStatement对象对应Mapper.xml配置文件中的一个select/update/insert/delete节点,描述的就是一条SQL语句
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);//wrapCollection(parameter),查询对应的参数,该执行器就是缓存执行器
} catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
4、query
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameterObject); CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);//二级缓存执行缓存相关逻辑。 return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);//二级缓存执行器执行 }
5.query
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { Cache cache = ms.getCache(); if (cache != null) { flushCacheIfRequired(ms); if (ms.isUseCache() && resultHandler == null) { ensureNoOutParams(ms, boundSql); @SuppressWarnings("unchecked") List<E> list = (List<E>) tcm.getObject(cache, key);//以上二级缓存相关逻辑 if (list == null) { list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);//正真的simpleexample执行器。 tcm.putObject(cache, key, list); // issue #578 and #116 } return list; } }