由于MapperMethod中Insert,update,delete这三个的执行方式是一样的,我们统一看一下
case INSERT: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
这里都是两步,①执行sqlsession的对应方法②对执行结果进行处理
1.执行sqlsession的对应方法:最终都是走的update方法
public int insert(String statement) {
return insert(statement, null);
}
@Override
public int insert(String statement, Object parameter) {
return update(statement, parameter);
}
@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);
}
@Override
public int update(String statement, Object parameter) {
try {
dirty = true;
//1.根据ID获取MappedStatement
MappedStatement ms = configuration.getMappedStatement(statement);
//2.对集合参数进行处理
//3.执行executor的update方法
return executor.update(ms, wrapCollection(parameter));
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
1.1根据ID获取MappedStatement 对象:缓存中获取
public MappedStatement getMappedStatement(String id) {
return this.getMappedStatement(id, true);
}
public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) {
if (validateIncompleteStatements) {
buildAllStatements();
}
return mappedStatements.get(id);
}
1.2对集合参数进行处理
private Object wrapCollection(final Object object) {
//如果是集合类型的参数
if (object instanceof Collection) {
//参数以,map形式返回
StrictMap<Object> map = new StrictMap<Object>();
//设置参数名称为collection
map.put("collection", object);
//如果是list类型
if (object instanceof List) {
//设置参数名称为list
map.put("list", object);
}
return map;
} else if (object != null && object.getClass().isArray()) {
//如果是数组类型,以map形式返回
//设置参数名称为array
StrictMap<Object> map = new StrictMap<Object>();
map.put("array", object);
return map;
}
//不是集合和数组类型 原样返回
return object;
}
1.3执行executor(BaseExecutor)的update方法
//这里主要是检验执行器的状态和关闭本地缓存
//真正的执行是调用的抽象方法 在实现类中
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);
}
默认情况我们都是走的SimpleExecutor,我们看一下这里的update方法实现
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
//1.获取配置类
Configuration configuration = ms.getConfiguration();
//2.获取StatementHandler 执行器
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
//3.获取Statement
stmt = prepareStatement(handler, ms.getStatementLog());
//4.StatementHandler 执行 update方法
return handler.update(stmt);
} finally {
closeStatement(stmt);
}
}
1.3.1获取配置类:ms.getConfiguration(),直接获取MappedStatement 中的Configuration变量
1.3.2获取StatementHandler 执行器
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//1.根据mappedStatement的Statementtype获取对应的StatementHandler
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
//2.在StatementHandler上添加插件拦截器
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
上图是StatementHandler 的实现关系图:我们看一下如何生成需要的真实对象的(是在RoutingStatementHandler初始化的时候完成的),一般情况我们都是预编译的StatementHandler(PreparedStatementHandler)
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());
}
}
1.3.3获取Statement:调用SimpleExecutor的prepareStatement方法
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
//1.获取数据库连接
Connection connection = getConnection(statementLog);
//2.调用StatementHandler生成Statement
stmt = handler.prepare(connection, transaction.getTimeout());
//3.设置参数信息
handler.parameterize(stmt);
return stmt;
}
1.3.3.1获取数据库连接:transaction --> dataSource
protected Connection getConnection(Log statementLog) throws SQLException {
//通过transaction事务里面的配置获取数据库连接
Connection connection = transaction.getConnection();
if (statementLog.isDebugEnabled()) {
//如果开启了日志debug模式 生成一个带有日志的连接
return ConnectionLogger.newInstance(connection, statementLog, queryStack);
} else {
return connection;
}
}
public Connection getConnection() throws SQLException {
if (connection == null) {
openConnection();
}
return connection;
}
protected void openConnection() throws SQLException {
if (log.isDebugEnabled()) {
log.debug("Opening JDBC Connection");
}
//调用的是dataSource的方法
connection = dataSource.getConnection();
if (level != null) {
connection.setTransactionIsolation(level.getLevel());
}
setDesiredAutoCommit(autoCommmit);
}
1.3.3.2调用StatementHandler生成Statement
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement = null;
try {
//根据数据库连接 初始化Statement
statement = instantiateStatement(connection);
//设置Statement的超时时间
setStatementTimeout(statement, transactionTimeout);
//设置Statement执行批量的大小
setFetchSize(statement);
return statement;
} catch (SQLException e) {
closeStatement(statement);
throw e;
} catch (Exception e) {
closeStatement(statement);
throw new ExecutorException("Error preparing statement. Cause: " + e, e);
}
}
//根据数据库连接 初始化Statement 最终都是通过Connection 去获取的Statement
protected Statement instantiateStatement(Connection connection) throws SQLException {
//获取执行的sql
String sql = boundSql.getSql();
//主键如果自增的话
if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
//获取主键字段
String[] keyColumnNames = mappedStatement.getKeyColumns();
//没有字段
if (keyColumnNames == null) {
return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
} else {
return connection.prepareStatement(sql, keyColumnNames);
}
} else if (mappedStatement.getResultSetType() != null) {
//返回类型不为空
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
} else {
return connection.prepareStatement(sql);
}
}
1.3.3.3设置参数信息
public void parameterize(Statement statement) throws SQLException {
parameterHandler.setParameters((PreparedStatement) statement);
}
这里调用的还是parameterHandler的方法,我们看一下parameterHandler是如何生成的:在初始化StatementHandler的时候,在构造方法中初始化了parameterHandler
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
//1.生成ParameterHandler
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
//添加相应的插件拦截器链
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
//1.生成ParameterHandler == DefaultParameterHandler
public ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
return new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
}
下面就是设置参数了
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
//获取所有入参信息
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
//获取参数字段名称
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
//获取参数类型处理器
TypeHandler typeHandler = parameterMapping.getTypeHandler();
//获取字段对应数据库字段类型
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
//设置参数的值
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
} catch (SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
//设置参数的值 其实就是设置给PreparedStatement
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
if (parameter == null) {
if (jdbcType == null) {
throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
}
try {
ps.setNull(i, jdbcType.TYPE_CODE);
} catch (SQLException e) {
throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " +
"Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " +
"Cause: " + e, e);
}
} else {
try {
setNonNullParameter(ps, i, parameter, jdbcType);
} catch (Exception e) {
throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . " +
"Try setting a different JdbcType for this parameter or a different configuration property. " +
"Cause: " + e, e);
}
}
}
1.3.4StatementHandler (PreparedStatementHandler)执行 update方法
public int update(Statement statement) throws SQLException {
//这接执行PreparedStatement 的execute方法操作数据库
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
//获取执行成功的条数
int rows = ps.getUpdateCount();
//处理selectKey的情况
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
return rows;
}
2.对执行结果进行处理
private Object rowCountResult(int rowCount) {
final Object result;
//方法返回是void
if (method.returnsVoid()) {
result = null;
} else if (Integer.class.equals(method.getReturnType()) || Integer.TYPE.equals(method.getReturnType())) {
//返回的是Integer类型
result = rowCount;
} else if (Long.class.equals(method.getReturnType()) || Long.TYPE.equals(method.getReturnType())) {
//返回的是Long类型
result = (long)rowCount;
} else if (Boolean.class.equals(method.getReturnType()) || Boolean.TYPE.equals(method.getReturnType())) {
//返回的是Boolean类型
result = rowCount > 0;
} else {
//抛出异常,返回的格式不正确
throw new BindingException("Mapper method '" + command.getName() + "' has an unsupported return type: " + method.getReturnType());
}
return result;
}
到这里Insert,update,delete的执行全过程就解析结束了。