mybatis执行sql过程 - 969251639/study GitHub Wiki
下面分析一个查询和一个更新的流程
mybtais获取到session后就可以对sql进行操作
public class DefaultSqlSession implements SqlSession {
...
@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();
}
}
@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();
}
}
...
}
1. 查询
获取mapper信息
MappedStatement ms = configuration.getMappedStatement(statement);
这样便知道了要执行的sql,参数,返回值等基础信息
然后通过执行器(默认为SIMPLE)调用查询
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameter);//绑定sql
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);//根据mapper,参数,分页,sql生成缓存key
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);//查询
}
@SuppressWarnings("unchecked")
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
...
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
...
}
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
...
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
...
}
@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);//创建一个handler,拦截扩展用
stmt = prepareStatement(handler, ms.getStatementLog());//通过数据库连接获取statement
return handler.<E>query(stmt, resultHandler);//执行sql查询
} finally {
closeStatement(stmt);
}
}
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);//打开数据库连接
stmt = handler.prepare(connection, transaction.getTimeout());获取statement
handler.parameterize(stmt);
return stmt;
}
要注意的是上面在获取Statement时是通过handler去拿的
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);//返回代理对象
return statementHandler;
}
默认生成的是RoutingStatementHandler
public class RoutingStatementHandler implements StatementHandler {
private final StatementHandler delegate;
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
switch (ms.getStatementType()) {
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case CALLABLE:
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
}
@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
return delegate.prepare(connection, transactionTimeout);
}
...
}
所以具体生成那种statement在构造RoutingStatementHandler的时候就已经确定了,默认是PREPARED
public final class MappedStatement {
...
public static class Builder {
private MappedStatement mappedStatement = new MappedStatement();
public Builder(Configuration configuration, String id, SqlSource sqlSource, SqlCommandType sqlCommandType) {
...
mappedStatement.statementType = StatementType.PREPARED;
...
}
...
}
所以最后执行查询的是PreparedStatementHandler
return handler.<E>query(stmt, resultHandler);//执行sql查询
最好的查询就是用原生的jdbc的PreparedStatement去查询数据库,最后封装成结果返回
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.<E> handleResultSets(ps);
}
...
}
**2. 更新**
更新那里会先将参数dirty置为true,表示数据已有变动,用来控制事务的提交和回滚
@Override public int update(String statement, Object parameter) { ... dirty = true; ... } private boolean isCommitOrRollbackRequired(boolean force) { //如果是非自动提交且数据已有变更 或者 强制提交(默认false) 返回true return (!autoCommit && dirty) || force; }
@Override public void commit() { commit(false); }
@Override public void commit(boolean force) { try { executor.commit(isCommitOrRollbackRequired(force)); dirty = false; } catch (Exception e) { throw ExceptionFactory.wrapException("Error committing transaction. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } @Override public void rollback() { rollback(false); }
@Override public void rollback(boolean force) { try { executor.rollback(isCommitOrRollbackRequired(force)); dirty = false; } catch (Exception e) { throw ExceptionFactory.wrapException("Error rolling back transaction. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
然后获取mapper信息
MappedStatement ms = configuration.getMappedStatement(statement);
这样便知道了要执行的sql,参数,返回值等基础信息
然后通过执行器(默认为SIMPLE)调用更新
return executor.update(ms, wrapCollection(parameter));
@Override public int update(MappedStatement ms, Object parameter) throws SQLException { ... return doUpdate(ms, parameter); } @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); } }
流程跟查一样,需要获取handler,发然拿到Statement,最后执行update
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; } ... }