Mybatis中DAO执行过程源码分析

67 阅读8分钟

文章目录


1. 查询所有方法源码分析

DAO接口的实现类调用了SqlSession.selectList()

public class AccountDaoImpl implements AccountDao {

    private SqlSessionFactory factory;

    public AccountDaoImpl(SqlSessionFactory factory) {
        this.factory = factory;
    }

    public List<Account> findAll() {
        SqlSession session = factory.openSession();
        List<Account> user = session.selectList("dao.AccountDao.findAll");
        session.close();
        return user;
    }
}

findAll()中调用的session.selectList(),发现SqlSession是一个借口,我们就需要找它的实现类

public interface SqlSession extends Closeable {

  <E> List<E> selectList(String statement);

  <E> List<E> selectList(String statement, Object parameter);

  <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);
}

这里使用的SqlSession的实现类为DefaultSqlSession,它其中的selectList()方法的实现如下所示:

public class DefaultSqlSession implements SqlSession {  
  @Override
    public <E> List<E> selectList(String statement) {
      return this.selectList(statement, null);
    }

    @Override
    public <E> List<E> selectList(String statement, Object parameter) {
      return this.selectList(statement, parameter, RowBounds.DEFAULT);
    }

    @Override
    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
      try {
        MappedStatement ms = configuration.getMappedStatement(statement);
        return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
      } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
      } finally {
        ErrorContext.instance().reset();
      }
    }
}

三个selectList()依次调用下一个,最终使用的是selectList(String statement, Object parameter, RowBounds rowBounds)。它其中又调用了executor.query(),executor的定义为private final Executor executor;,而Executor是一个接口:

public interface Executor {
  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;

  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
}

因此,我们有需要找Executor的实现类。这里使用的是CachingExecutor

public class CachingExecutor implements Executor {
  private final Executor delegate;
  
  @Override
  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);
  }
  
  @Override
  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);
          tcm.putObject(cache, key, list); // issue #578 and #116
        }
        return list;
      }
    }
    return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }
}

其中又调用了delegate.query,delegate本身又是Executor类型的变量。因此,我们需要找到delegate对应的Executor接口的实现类,这里使用的是BaseExecutor。

public abstract class BaseExecutor implements Executor {
  @SuppressWarnings("unchecked")
  @Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      if (list != null) {
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
      // issue #601
      deferredLoads.clear();
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        // issue #482
        clearLocalCache();
      }
    }
    return list;
  }
}

其中又调用了queryFromDatabase()

private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    List<E> list;
    localCache.putObject(key, EXECUTION_PLACEHOLDER);
    try {
      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    } finally {
      localCache.removeObject(key);
    }
    localCache.putObject(key, list);
    if (ms.getStatementType() == StatementType.CALLABLE) {
      localOutputParameterCache.putObject(key, parameter);
    }
    return list;
  }

其中调用了doQuery()。Executor本身是一个抽象类,故还需要继续找它的实现类SimpleExecutor中doQuery()的实现:

public class SimpleExecutor extends BaseExecutor {

  @Override
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }
}

其中调用了handler.query(),handler的定义为StatementHandler handler,其中的StatementHandler 是以一个接口。这里接口的实现类使用的是RoutingStatementHandler

public class RoutingStatementHandler implements StatementHandler {
  @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    return delegate.query(statement, resultHandler);
  }
}

而这里的delegate是StatementHandler接口的实现类PreparedStatementHandler类型的变量。

public class PreparedStatementHandler extends BaseStatementHandler {

  @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();
    return resultSetHandler.handleResultSets(ps);
  }
}

PreparedStatementHandler中的query()使用的就是JDBC中的PreparedStatement的execute(),结果的封装使用了resultSetHandler接口的唯一实现类DefaultResultSetHandler中的handleResultSets()

public class DefaultResultSetHandler implements ResultSetHandler {
  @Override
  public List<Object> handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());

    final List<Object> multipleResults = new ArrayList<>();

    int resultSetCount = 0;
    ResultSetWrapper rsw = getFirstResultSet(stmt);

    List<ResultMap> resultMaps = mappedStatement.getResultMaps();
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
    while (rsw != null && resultMapCount > resultSetCount) {
      ResultMap resultMap = resultMaps.get(resultSetCount);
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    }
  }

PreparedStatement对象的执行方法:

  • execute():它能执行CRUD中的任意一种语句,返回值是boolean类型,表示是否有结果集,有结果集是true,否则是false
  • executeUpdate():它只能执行CUD语句,查询语句无法执行,返回值为影响数据库记录的行数
  • executeQuery():它只能执行SELECT语句,无法执行增删改,执行结果封装的结果集ResultSet对象

2. 插入、更新、删除方法源码分析

DAO接口的实现类中插入方法的实现:

public class AccountDaoImpl implements AccountDao {
    private SqlSessionFactory factory;

    public AccountDaoImpl(SqlSessionFactory factory) {
        this.factory = factory;
    }

    public void saveUser(Account account) {
        SqlSession session = factory.openSession();
        session.insert("dao.AccountDao.saveUser", account);
        session.commit();
        session.close();
    }
}

调用的是SqlSession的实现类DefaultSqlSession中的insert()

public class DefaultSqlSession implements SqlSession {
  @Override
  public int insert(String statement) {
    return insert(statement, null);
  }

  @Override
  public int insert(String statement, Object parameter) {
    return update(statement, parameter);
  }
}

insert()调用的是update()

DAO接口的实现类中更新方法的实现:

public class AccountDaoImpl implements AccountDao {
    private SqlSessionFactory factory;

    public AccountDaoImpl(SqlSessionFactory factory) {
        this.factory = factory;
    }

    public void updateUser(Account account) {
        SqlSession session = factory.openSession();
        session.update("dao.AccountDao.updateUser", account);
        session.commit();
        session.close();

    }
}

它调用的是SqlSession的实现类DefaultSqlSession中的update()

public class DefaultSqlSession implements SqlSession {
  @Override
  public int update(String statement) {
    return update(statement, null);
  }

  @Override
  public int update(String statement, Object parameter) {
    try {
      dirty = true;
      MappedStatement ms = configuration.getMappedStatement(statement);
      return executor.update(ms, wrapCollection(parameter));
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }
}

DAO接口的实现类中删除方法的实现:

public class AccountDaoImpl implements AccountDao {
    private SqlSessionFactory factory;

    public AccountDaoImpl(SqlSessionFactory factory) {
        this.factory = factory;
    }

    public void deleteUser(int id) {
        SqlSession session = factory.openSession();
        session.update("dao.AccountDao.deleteUser", id);
        session.commit();
        session.close();

    }
}

它调用的是SqlSession的实现类DefaultSqlSession中的update()

public class DefaultSqlSession implements SqlSession {
  @Override
  public int update(String statement) {
    return update(statement, null);
  }

  @Override
  public int delete(String statement) {
    return update(statement, null);
  }

  @Override
  public int delete(String statement, Object parameter) {
    return update(statement, parameter);
  }
}

delete()又调用了update()

综上,三种方法最终调用的都是DefaultSqlSession中的update(),因此,后面只需要分析update()的源码实现即可。

update()中调用了executor.update(),这里的executor使用的是Executor接口的实现类CachingExecutor中的方法实现。

public class CachingExecutor implements Executor {
  private final Executor delegate;
  
  @Override
  public int update(MappedStatement ms, Object parameterObject) throws SQLException {
    flushCacheIfRequired(ms);
    return delegate.update(ms, parameterObject);
  }
}

方法中调用了delegate.update(),这里调用的是Executor的实现类BaseExecutor中的update()

public abstract class BaseExecutor implements Executor {
  @Override
  public int update(MappedStatement ms, Object parameter) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    clearLocalCache();
    return doUpdate(ms, parameter);
  }
}

update()方法实现又调用了doUpdate()

  protected abstract int doUpdate(MappedStatement ms, Object parameter)
      throws SQLException;

它是一个抽象方法,找到BaseExecutor的实现类SimpleExecutor中的doUpdate()

public class SimpleExecutor extends BaseExecutor {

  @Override
  public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.update(stmt);
    } finally {
      closeStatement(stmt);j
    }
  }
}

其中调用了handler.update(),这里的handler为StatementHandler类型,StatementHandler本身又是一个接口,需要找到它的实现类。直接实现类为BaseStatementHandler,它是一个抽象类,它的实现类PreparedStatementHandler。

public class PreparedStatementHandler extends BaseStatementHandler {
  @Override
  public int update(Statement statement) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();
    int rows = ps.getUpdateCount();
    Object parameterObject = boundSql.getParameterObject();
    KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
    keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
    return rows;
  }
}

其中的update()使用的仍然是JDBC中的PreparedStatement的execute()


3. 聚合函数getCount的源码分析

DAO接口的实现类中getCount()的实现:

public class AccountDaoImpl implements AccountDao {
    private SqlSessionFactory factory;
    public int getCount() {
        SqlSession session = factory.openSession();
        int count = session.selectOne("dao.AccountDao.getCount");
        session.close();
        return count;
    }
}

调用了SqlSession.selectOne()。找SqlSession接口的实现类DefaultSqlSession中的selectOne()

public class DefaultSqlSession implements SqlSession {
  @Override
  public <T> T selectOne(String statement) {
    return this.selectOne(statement, null);
  }

  @Override
  public <T> T selectOne(String statement, Object parameter) {
    // Popular vote was to return null on 0 results and throw exception on too many.
    List<T> list = this.selectList(statement, parameter);
    if (list.size() == 1) {
      return list.get(0);
    } else if (list.size() > 1) {
      throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
    } else {
      return null;
    }
  }
}

它又调用了DefaultSqlSession中的selectList()

  @Override
  public <E> List<E> selectList(String statement) {
    return this.selectList(statement, null);
  }

  @Override
  public <E> List<E> selectList(String statement, Object parameter) {
    return this.selectList(statement, parameter, RowBounds.DEFAULT);
  }

  @Override
  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      MappedStatement ms = configuration.getMappedStatement(statement);
      return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

selectList()中又调用了executor.query()。这里同样找到Executor接口的实现类CachingExecutor中的方法实现。

public class CachingExecutor implements Executor {
  @Override
  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);
          tcm.putObject(cache, key, list); // issue #578 and #116
        }
        return list;
      }
    }
    return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }
}

它又调用了delegate.query()。delegate的类型为Executor的实现类CachingExecutor,继续看它的方法实现

public class CachingExecutor implements Executor {
  @Override
  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);
          tcm.putObject(cache, key, list); // issue #578 and #116
        }
        return list;
      }
    }
    return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }
}

其中又调用了delegate.query,delegate本身又是Executor类型的变量。因此,我们需要找到delegate对应的Executor接口的实现类,这里使用的是BaseExecutor。

public abstract class BaseExecutor implements Executor {
  @SuppressWarnings("unchecked")
  @Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      if (list != null) {
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
      // issue #601
      deferredLoads.clear();
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        // issue #482
        clearLocalCache();
      }
    }
    return list;
  }
}

其中又调用了queryFromDatabase()

private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    List<E> list;
    localCache.putObject(key, EXECUTION_PLACEHOLDER);
    try {
      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    } finally {
      localCache.removeObject(key);
    }
    localCache.putObject(key, list);
    if (ms.getStatementType() == StatementType.CALLABLE) {
      localOutputParameterCache.putObject(key, parameter);
    }
    return list;
  }

其中调用了doQuery()。Executor本身是一个抽象类,故还需要继续找它的实现类SimpleExecutor中doQuery()的实现:

public class SimpleExecutor extends BaseExecutor {

  @Override
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }
}

其中调用了handler.query(),handler的定义为StatementHandler handler,其中的StatementHandler 是以一个接口。这里接口的实现类使用的是RoutingStatementHandler

public class RoutingStatementHandler implements StatementHandler {
  @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    return delegate.query(statement, resultHandler);
  }
}

而这里的delegate是StatementHandler接口的实现类PreparedStatementHandler类型的变量。

public class PreparedStatementHandler extends BaseStatementHandler {

  @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();
    return resultSetHandler.handleResultSets(ps);
  }
}

PreparedStatementHandler中的query()使用的就是JDBC中的PreparedStatement的execute(),结果的封装使用了resultSetHandler接口的唯一实现类DefaultResultSetHandler中的handleResultSets()

public class DefaultResultSetHandler implements ResultSetHandler {
  @Override
  public List<Object> handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());

    final List<Object> multipleResults = new ArrayList<>();

    int resultSetCount = 0;
    ResultSetWrapper rsw = getFirstResultSet(stmt);

    List<ResultMap> resultMaps = mappedStatement.getResultMaps();
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
    while (rsw != null && resultMapCount > resultSetCount) {
      ResultMap resultMap = resultMaps.get(resultSetCount);
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    }
  }