1. 在创建好sqlSessionFactory之后,接着就要配置sqlSession的创建。

<bean id="simpleTempalte" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
<constructor-arg index="1" value="SIMPLE" />
</bean>
  • 构造参数,包括sqlSessionFactory对象,以及ExecutorType(simple)

2. sqlSession接口

mybatis源码分析(2)-----SqlSession创建-LMLPHP

  • 我们的应用程序,是直接注入sqlSessionTemplate ,操作数据库
simpleTempalte.delete(Statement.getStatement(CxCaseMapper.class, "deleteById"), id);
  • 实现类sqlSessionTemplate
public class SqlSessionTemplate implements SqlSession {
//session 工场的引用
private final SqlSessionFactory sqlSessionFactory;
// 对于数据库的操作类型
private final ExecutorType executorType;
//sqlSession代理
private final SqlSession sqlSessionProxy;
private final PersistenceExceptionTranslator exceptionTranslator;
}
  • sqlSession对每一个数据库的操作,实际上是引用代理对象sqlSessionProxy 对于目标方法的执行。
  @Override
public int delete(String statement) {
return this.sqlSessionProxy.delete(statement);
}
  • 在构造方法中,给代理对象已经其他属性赋予的默认值
    public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
PersistenceExceptionTranslator exceptionTranslator) {
this.sqlSessionFactory = sqlSessionFactory;
this.executorType = executorType;
this.exceptionTranslator = exceptionTranslator;
//构造代理对象
this.sqlSessionProxy = (SqlSession) newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[] { SqlSession.class },
new SqlSessionInterceptor());
} private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //这里获取的sqlSession 其实是DefaultSqlSession
SqlSession sqlSession = getSqlSession(
SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType,
SqlSessionTemplate.this.exceptionTranslator);
try {
// 代理对象对于目标对象的调用,其实是defaultSqlSession 对于目标方法的调用
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) {
//调用目标方法后,关闭Session。 后续会重点讲解
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
}
  • defaultSqlSession 对于目标方法的执行
public class DefaultSqlSession implements SqlSession {

  private Configuration configuration;
private Executor executor; private boolean autoCommit;
private boolean dirty; @Override
public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
executor.query(ms, wrapCollection(parameter), rowBounds, handler);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
} }

3.   代理的优点

  无论是多个dao使用一个SqlSessionTemplate,还是一个dao使用一个SqlSessionTemplate,SqlSessionTemplate都是对应一个sqlSession,当多个web线程调用同一个dao时,它们使用的是同一个SqlSessionTemplate,也就是同一个SqlSession,保证线程安全,

4 .总结

mybatis源码分析(2)-----SqlSession创建-LMLPHP

04-15 01:31