SqlSessionTemplate

加瓦攻城獅發表於2017-11-20

mybatis中SqlSessionTemplate實現了SqlSession介面

如下面原始碼中,這裡使用SqlSessionInterceptor這個內部類,來生成了一個SqlSession的代理物件:

public class SqlSessionTemplate implements SqlSession {  private final SqlSessionFactory sqlSessionFactory;  private final ExecutorType executorType;  private final SqlSession sqlSessionProxy;  private final PersistenceExceptionTranslator exceptionTranslator;  /**   * Constructs a Spring managed SqlSession with the {@code SqlSessionFactory}   * provided as an argument.   *   * @param sqlSessionFactory   */  public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {    this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());  }  /**   * Constructs a Spring managed SqlSession with the {@code SqlSessionFactory}   * provided as an argument and the given {@code ExecutorType}   * {@code ExecutorType} cannot be changed once the {@code SqlSessionTemplate}   * is constructed.   *   * @param sqlSessionFactory   * @param executorType   */  public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {    this(sqlSessionFactory, executorType,        new MyBatisExceptionTranslator(            sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true));  }  /**   * Constructs a Spring managed {@code SqlSession} with the given   * {@code SqlSessionFactory} and {@code ExecutorType}.   * A custom {@code SQLExceptionTranslator} can be provided as an   * argument so any {@code PersistenceException} thrown by MyBatis   * can be custom translated to a {@code RuntimeException}   * The {@code SQLExceptionTranslator} can also be null and thus no   * exception translation will be done and MyBatis exceptions will be   * thrown   *   * @param sqlSessionFactory   * @param executorType   * @param exceptionTranslator   */  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;    this.sqlSessionProxy = (SqlSession) newProxyInstance(        SqlSessionFactory.class.getClassLoader(),        new Class[] { SqlSession.class },        new SqlSessionInterceptor());  }複製程式碼

SqlSessionInterceptor:

private class SqlSessionInterceptor implements InvocationHandler {    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {      SqlSession sqlSession = getSqlSession(          SqlSessionTemplate.this.sqlSessionFactory,          SqlSessionTemplate.this.executorType,          SqlSessionTemplate.this.exceptionTranslator);      try {        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);        }      }    }  }複製程式碼

如上,在Interceptor中定義了sqlSession的commit,close