Mybatis源码分析-SqlSessionTemplate
2017-08-01 18:05
1076 查看
SqlSessionFactory生成
在spring中,SqlSessionFactory的生成是通过SqlSessionFactoryBean生成的,如下protected SqlSessionFactory buildSqlSessionFactory() throws IOException { **** **** return this.sqlSessionFactoryBuilder.build(configuration); }
创建的SqlSessionFactory对象为
DefaultSqlSessionFactory
public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }
MapperFactoryBean父类SqlSessionDaoSupport-持久层创建
private SqlSession sqlSession; private boolean externalSqlSession; public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { if (!this.externalSqlSession) { //包装成SqlSessionTemplate对象 this.sqlSession = new SqlSessionTemplate(sqlSessionFactory); } }
mybatis持久层的操作都会被包装成SqlSessionTemplate对象
SqlSessionTemplate构造函数
基本都是由SqlSessionFactory作为入参
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { //默认的ExecutorType为ExecutorType.SIMPLE this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType()); }
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; //对数据库的操作也会包装成代理的形式,所有的CRUD操作则都由sqlSessionProxy对象来完成 this.sqlSessionProxy = (SqlSession) newProxyInstance( SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSession.class }, new SqlSessionInterceptor()); }
我们迫在眉睫的需要了解sqlSession代理的处理流程
SqlSessionTemplate#SqlSessionInterceptor
其是一个内部私有类private class SqlSessionInterceptor implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //通过SqlSessionUtils.getSqlSession()获得真实处理CRUD的持久层,默认为DefaultSqlSession SqlSession sqlSession = getSqlSession( SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator); try { //执行CRUD操作 Object result = method.invoke(sqlSession, args); //非事务处理的数据操作需要强制commit if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { // force commit even on non-dirty sessions because some databases require // a commit/rollback before calling close() sqlSession.commit(true); } return result; } catch (Throwable t) { Throwable unwrapped = unwrapThrowable(t); if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) { // release the connection to avoid a deadlock if the translator is no loaded. See issue #22 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); sqlSession = null; //翻译异常 Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped); if (translated != null) { unwrapped = translated; } } throw unwrapped; } finally { if (sqlSession != null) { //关闭sqlSession,再上一个保险,避免占用shuju closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); } } } }
创建sqlSession的步骤是通过SqlSessionUtils#getSqlSession()来完成的,我们必须需要仔细分析
SqlSessionUtils#getSqlSession()-获取真实的持久层操作对象
其实本质是从SqlSessionFactory中创建SqlSession的,这里只是作下缓存SqlSessionpublic static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { notNull(sessionFactory, "No SqlSessionFactory specified"); notNull(executorType, "No ExecutorType specified"); //尝试从ThreadLocal中获取SqlSessionHolder,类似缓存 SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); if (holder != null && holder.isSynchronizedWithTransaction()) { //不允许再次获取的SqlSession修改executorType if (holder.getExecutorType() != executorType) { throw new TransientDataAccessResourceException("Cannot change the ExecutorType when there is an existing transaction"); } //对引用同一个SqlSession的计数 holder.requested(); return holder.getSqlSession(); } //通过SqlSessionFactory创建SqlSession SqlSession session = sessionFactory.openSession(executorType); //判断是否是同步的 if (TransactionSynchronizationManager.isSynchronizationActive()) { Environment environment = sessionFactory.getConfiguration().getEnvironment(); //TransactionFactory默认的为SpringManagedTransactionFactory if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) { //创建SqlSessionHolder并缓存在ThreadLocal中 holder = new SqlSessionHolder(session, executorType, exceptionTranslator); TransactionSynchronizationManager.bindResource(sessionFactory, holder); TransactionSynchronizationManager.registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory)); holder.setSynchronizedWithTransaction(true); holder.requested(); } else { if (TransactionSynchronizationManager.getResource(environment.getDataSource()) == null) { } else { throw new TransientDataAccessResourceException( "SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization"); } } } return session; }
我们知道上述的SqlSessionFactory为
DefaultSqlSessionFactory,下面看下其如何创建SqlSession
DefaultSqlSessionFactory#openSessionFromDataSource
源码奉上//默认情况下,参数值为ExecutorType.SIMPLE/null/false private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { //事务接口对象 Transaction tx = null; try { final Environment environment = configuration.getEnvironment(); //此处的TransactionFactory为SpringManagedTransactionFactory final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); //创建事务对象 tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); //创建线程池,根据execType,默认为SimpleExecutor并支持缓存 final Executor executor = configuration.newExecutor(tx, execType); //返回DefaultSqlSession return new DefaultSqlSession(configuration, executor, autoCommit); } 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(); } }
默认的事务对象则是由
SpringManagedTransactionFactory来创建的,内含dataSource数据源,且不自动提交
默认的Executor线程池则为SimpleExecutor并支持缓存,另外还有BatchExecutor/ReuseExecutor线程池。根据ExecutorType判断
默认创建的SqlSession对象为
DefaultSqlSession,内含事务对象、线程池、Configuration对象
SqlSessionTemplate#CRUD操作
根据前文的分析,SqlSessionTemplate的CRUD操作是由MapperMethod#execute()方法调用的,其中传给sqlSession的参数为
mappedStatementId和其中的方法参数集合
public Object execute(SqlSession sqlSession, Object[] args) { Object result; if (SqlCommandType.INSERT == command.getType()) { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.insert(command.getName(), param)); } else if (SqlCommandType.UPDATE == command.getType()) { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.update(command.getName(), param)); } else if (SqlCommandType.DELETE == command.getType()) { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.delete(command.getName(), param)); } else if (SqlCommandType.SELECT == command.getType()) { if (method.returnsVoid() && method.hasResultHandler()) { executeWithResultHandler(sqlSession, args); result = null; } else if (method.returnsMany()) { result = executeForMany(sqlSession, args); } else if (method.returnsMap()) { result = executeForMap(sqlSession, args); } else { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); } } else { throw new BindingException("Unknown execution method for: " + command.getName()); } if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { throw new BindingException("Mapper method '" + command.getName() + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; }
简单梳理下service层调用CRUD操作的实现步骤
service层调用dao数据层方法-->读取对应接口dao的MapperFactoryBean#getObject()方法
-->SqlSessionTemplate#getMapper()方法-->得到MapperProxy代理类并调用对应接口方法的MapperMethod
-->以
接口类+method方法名作为mappedStatementId读取MappedStatement对象以获取SqlCommand指令-->根据SqlCommand指令调用SqlSessionTemplate对应的CRUD操作,一般为select()/delete()/update()/insert()方法
-->sqlSessionProxy代理调用真实数据层处理类DefaultSqlSession对应的CRUD操作-->MappedStatement对象处理数据库sql语句
-->返回结果集供MapperMethod处理返回给service层
CREATE/UPDATE/DELETE
简单从CREATE操作看,先看SqlSessionTempate#insert()方法public int insert(String statement) { return this.sqlSessionProxy.insert(statement); }
进而观察DefaultSqlSession#insert()方法
public int insert(String statement) { return insert(statement, null); }
public int insert(String statement, Object parameter) { return update(statement, parameter); }
进行仔细的观察我们得知,除了select语句,其实调用的都是update方法
public int update(String statement, Object parameter) { try { dirty = true; //根据statement得到相应的MappedStatement对象 MappedStatement ms = configuration.getMappedStatement(statement); //最终调用Executor线程池来进行相应的操作 return executor.update(ms, wrapCollection(parameter)); } catch (Exception e) { throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
而其中的wrapCollection()方法则是将参数分门别类下
//StrictMap就是普通的HashMap,只是在get方法上加了必须存在相应key的判断 private Object wrapCollection(final Object object) { if (object instanceof List) { StrictMap<Object> map = new StrictMap<Object>(); map.put("list", object); return map; } else if (object != null && object.getClass().isArray()) { StrictMap<Object> map = new StrictMap<Object>(); map.put("array", object); return map; } return object; }
SELECT
直接转进DefaultSqlSession#select()通用方法public void select(String statement, Object parameter, ResultHandler handler) { select(statement, parameter, RowBounds.DEFAULT, handler); }
public void select(String statement, ResultHandler handler) { select(statement, null, RowBounds.DEFAULT, handler); }
public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) { try { MappedStatement ms = configuration.getMappedStatement(statement); //调用线程池的query方法来获取,获取到的值存放到ResultHandler内部属性中 executor.query(ms, wrapCollection(parameter), rowBounds, handler); } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
小结
SqlSessionTemplate接受dao层的CRUD请求,通过代理调用DefaultSqlSession的CRUD操作
DefaultSqlSession的内部操作都是通过
org.apache.ibatis.executor.Executor处理然后返回结果的
相关文章推荐
- Mybatis-Spring SqlSessionTemplate 源码解析
- mybatis源码分析(1)——SqlSessionFactory实例的产生过程
- Mybatis SqlSessionTemplate 源码解析
- mybatis源码分析(1)-----sqlSessionFactory创建
- MyBatis 之 SqlSessionManager 源码分析
- Mybatis SqlSessionTemplate 源码解析
- mybatis源码分析之SqlSession的创建过程
- Mybatis SqlSessionTemplate 源码解析
- Mybatis 源码分析一、 SqlSessionFactory的创建过程
- mybatis源码分析——SqlSessionFactory实例的产生过程
- MyBatis-3.4.2-源码分析18:XML解析之RoleMapper userMapper = sqlSession.getMapper(RoleMapper.class)
- MyBatis源码分析——SqlSessionFactory实例的产生过程
- MyBatis 源码分析 之SqlSession接口和Executor类
- Mybatis架构设计及源码分析-SqlSessionFactory
- Mybatis SqlSessionTemplate 源码解析
- Mybatis工作机制源码分析—SqlSessionUtils.getSqlSession工作机制
- 【Mybatis源码分析】01-SqlSessionFactory的创建过程
- Mybatis SqlSessionTemplate 源码解析
- Mybatis SqlSessionTemplate 源码解析
- mybatis源码分析(一,sqlSessionFactory的创建流程)