Mybatis的SqlSession理解
Posted 暖暖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis的SqlSession理解相关的知识,希望对你有一定的参考价值。
Mybaits加载执行该xml配置
class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean
spring 在初始化 sqlsessionbean的时候通过createBean调用了在SqlSessionFactoryBean中实现了接口InitializingBean的afterPropertiesSet()方法在该方法中调用了buildSqlSessionFactory()开始创建SqlSessionFactory
buildSqlSessionFactory()方法完成以下功能
一:
a) 创建configuration
b) typeAliasesPackage
c) typeAliases TYPE_ALIASES将类型存放到此map里面同b
d) plugins configuration添加插件
e) typeHandlersPackage
f) typeHandlers
g) xmlConfigBuilder.parse()将所有的配置从xml中读取并放入到对应的变量里面
h) mapperLocations
二:xmlMapperBuilder.parse()——> configurationElement
a) parameterMapElement(context.evalNodes("/mapper/parameterMap"));将mapper.xml中的prameterMap节点的数据添加到configuration.parameterMaps中
b) resultMapElements(context.evalNodes("/mapper/resultMap"));将mapper.xml中的resultMap节点的数据添加到configuration.incompleteResultMaps中
c) sqlElement(context.evalNodes("/mapper/sql"));
d) buildStatementFromContext(select|insert|update|delete);buildStatementFromContext:从mapper 中获取sql语句,执行类型(增删改查),parseStatementNode中addMappedStatement创建每个mapper对应的方法创建MappedStatement并添加到 configuration.mappedStatements.put(com.qb.mysql.dao.TRoleDao.getUserRoleByRid, MappedStatement)
最后返回了一个 DefaultSqlSessionFactory(config)
在调用SqlSessionTemplate进行dao层操作时,其会将工作委托给sqlSessionProxy属性进行,而sqlSessionProxy在进行相关method调用时,用到了JDK动态代理机制,首先SqlSessionUtils.getSqlSession获取sqlSession
private class SqlSessionInterceptor implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //返回一个DefaultSqlsession SqlSession sqlSession = getSqlSession( SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator); try { //调用该类的MapperProxy的invoke方法 Object result = method.invoke(sqlSession, args); 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) { closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); } } } }
在getSqlSession方法中创建事务,创建Executor,默认创建SimpleExecutor;InterceptorChain添加拦截器 InterceptorChain.pluginAll()
SqlSessionTemplate ->SqlSessionInterceptor->SqlSessionUtils. getSqlSession()->(defaultsqlsessionfactory)sessionFactory.openSession()->openSessionFromDataSource()
MapperProxy的invoke方法的方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } final MapperMethod mapperMethod = cachedMapperMethod(method); //执行execute return mapperMethod.execute(sqlSession, args); }
//根据sql类型选择对应的方法 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; }
SqlSessionTemplate 执行了创建sqlsession,openSqlsession,执行sql,closeSqlsession
以上是关于Mybatis的SqlSession理解的主要内容,如果未能解决你的问题,请参考以下文章
myBatis架构以及SQlSessionFactory,SqlSession,通过代理执行crud源码分析---待更
深入理解java:4.3.1. 框架编程之MyBatis---SQL语句执行的完整流程