mybatis源码解析10---StatementHandler解析

StatementHandler解析

接口的作用是statement处理器,位于mybatis包的org.apache.ibatis.executor.statement目录下,源码如下:

 1 package org.apache.ibatis.executor.statement;
 2 
 3 import java.sql.Connection;
 4 import java.sql.SQLException;
 5 import java.sql.Statement;
 6 import java.util.List;
 7 
 8 import org.apache.ibatis.executor.parameter.ParameterHandler;
 9 import org.apache.ibatis.mapping.BoundSql;
10 import org.apache.ibatis.session.ResultHandler;
11 
12 public interface StatementHandler {
13   
14   //sql预编译,构建Statement对象
15   Statement prepare(Connection connection)
16       throws SQLException;
17   
18   //对prepare方法构建的预编译的SQL进行参数的设置
19   void parameterize(Statement statement)
20       throws SQLException;
21    
22   //批量处理
23   void batch(Statement statement)
24       throws SQLException;
25 
26   //执行预编译后的SQL--update语句
27   int update(Statement statement)
28       throws SQLException;
29    
30   //执行预编译后的SQL--select语句
31   <E> List<E> query(Statement statement, ResultHandler resultHandler)
32       throws SQLException;
33   
34   //获取SQL封装类BoundSql对象
35   BoundSql getBoundSql();
36   
37   //获取参数处理器对象
38   ParameterHandler getParameterHandler();
39 
40 }

可见StatementHandler的作用就是先通过prepare方法构建一个Statement对象,然后再调用其他方法对Statement对象进行处理

StatementHandler和Executor类似,StatementHandler也有两个实现类,BaseStatementHandler和RoutingStatementHandler

而BaseStatement又有三个子类实现它的抽象方法,下面再挨个分析,先看最简单的BaseStatementHandler

BaseStatementHandler解析

BaseStatementHandler是一个抽象父类,有三个子类继承于它,源码如下:

  1 package org.apache.ibatis.executor.statement;
  2 
  3 import java.sql.Connection;
  4 import java.sql.SQLException;
  5 import java.sql.Statement;
  6 
  7 import org.apache.ibatis.executor.ErrorContext;
  8 import org.apache.ibatis.executor.Executor;
  9 import org.apache.ibatis.executor.ExecutorException;
 10 import org.apache.ibatis.executor.keygen.KeyGenerator;
 11 import org.apache.ibatis.executor.parameter.ParameterHandler;
 12 import org.apache.ibatis.executor.resultset.ResultSetHandler;
 13 import org.apache.ibatis.mapping.BoundSql;
 14 import org.apache.ibatis.mapping.MappedStatement;
 15 import org.apache.ibatis.reflection.factory.ObjectFactory;
 16 import org.apache.ibatis.session.Configuration;
 17 import org.apache.ibatis.session.ResultHandler;
 18 import org.apache.ibatis.session.RowBounds;
 19 import org.apache.ibatis.type.TypeHandlerRegistry;
 20 
 21 public abstract class BaseStatementHandler implements StatementHandler {
 22 
 23   protected final Configuration configuration;//全局配置
 24   protected final ObjectFactory objectFactory;//对象工厂
 25   protected final TypeHandlerRegistry typeHandlerRegistry;
 26   protected final ResultSetHandler resultSetHandler;//结果集处理器
 27   protected final ParameterHandler parameterHandler;//参数处理器
 28 
 29   protected final Executor executor;//执行器
 30   protected final MappedStatement mappedStatement;//mapper的SQL对象
 31   protected final RowBounds rowBounds;//分页参数
 32 
 33   protected BoundSql boundSql;//sql封装对象
 34 
 35   //构造方法
 36   protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
 37     this.configuration = mappedStatement.getConfiguration();
 38     this.executor = executor;
 39     this.mappedStatement = mappedStatement;
 40     this.rowBounds = rowBounds;
 41 
 42     this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
 43     this.objectFactory = configuration.getObjectFactory();
 44 
 45     if (boundSql == null) { // issue #435, get the key before calculating the statement
 46       generateKeys(parameterObject);
 47       boundSql = mappedStatement.getBoundSql(parameterObject);
 48     }
 49 
 50     this.boundSql = boundSql;
 51 
 52     this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
 53     this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
 54   }
 55 
 56   //返回boundSql
 57   public BoundSql getBoundSql() {
 58     return boundSql;
 59   }
 60 
 61   //返回parameterHandler
 62   public ParameterHandler getParameterHandler() {
 63     return parameterHandler;
 64   }
 65 
 66   //预编译SQL语句
 67   public Statement prepare(Connection connection) throws SQLException {
 68     ErrorContext.instance().sql(boundSql.getSql());
 69     Statement statement = null;
 70     try {
 71       statement = instantiateStatement(connection);//调用抽象方法构建statement对象是,但是没有具体实现,而是交给其子类去实现
 72       setStatementTimeout(statement);//设置statement超时时间
 73       setFetchSize(statement);//设置statement的fetchSize
 74       return statement;
 75     } catch (SQLException e) {
 76       closeStatement(statement);
 77       throw e;
 78     } catch (Exception e) {
 79       closeStatement(statement);
 80       throw new ExecutorException("Error preparing statement.  Cause: " + e, e);
 81     }
 82   }
 83 
 84   protected abstract Statement instantiateStatement(Connection connection) throws SQLException;
 85 
 86   //给statement对象设置timeout
 87   protected void setStatementTimeout(Statement stmt) throws SQLException {
 88     Integer timeout = mappedStatement.getTimeout();
 89     Integer defaultTimeout = configuration.getDefaultStatementTimeout();
 90     if (timeout != null) {
 91       stmt.setQueryTimeout(timeout);
 92     } else if (defaultTimeout != null) {
 93       stmt.setQueryTimeout(defaultTimeout);
 94     }
 95   }
 96 
 97   //给statement对象设置fetchSize
 98   protected void setFetchSize(Statement stmt) throws SQLException {
 99     Integer fetchSize = mappedStatement.getFetchSize();
100     if (fetchSize != null) {
101       stmt.setFetchSize(fetchSize);
102     }
103   }
104 
105   //关闭statement
106   protected void closeStatement(Statement statement) {
107     try {
108       if (statement != null) {
109         statement.close();
110       }
111     } catch (SQLException e) {
112       //ignore
113     }
114   }
115 
116    //根据参数对象生成key
117   protected void generateKeys(Object parameter) {
118     KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
119     ErrorContext.instance().store();
120     keyGenerator.processBefore(executor, mappedStatement, null, parameter);
121     ErrorContext.instance().recall();
122   }
123 
124 }

可以看出BaseStatementHandler只是实现了StatementHandler的三个方法,其中getBoundSql和getParameterHandler方法只是返回了由构造方法初始化的boundSql和parameterHandler属性,

而prepare方法是用于构建Statement对象的,但是BaseStatementHandler只是调用了自身的抽象方法instantiateStatement来创建,然后对statement对象进行其他处理,但是创建的过程则没有实现,而是交给了其子类去实现。

BaseStatementHandler有三个子类,分别为:
SimpleStatememtHandler:最简单的StatementHandler,处理不带参数运行的SQL
PreparedStatementHandler:预处理Statement的handler,处理带参数允许的SQL
CallableStatementHandler:存储过程的Statement的handler,处理存储过程SQL

先来看最简单的SimpleStatementHandler,它继承于BaseStatementHandler,所以它需要实现StatementHandler的接口,还需要重写父类BaseStatementHandler的抽象方法,源码如下:

 1 package org.apache.ibatis.executor.statement;
 2 
 3 import java.sql.Connection;
 4 import java.sql.ResultSet;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 import java.util.List;
 8 
 9 import org.apache.ibatis.executor.Executor;
10 import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
11 import org.apache.ibatis.executor.keygen.KeyGenerator;
12 import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
13 import org.apache.ibatis.mapping.BoundSql;
14 import org.apache.ibatis.mapping.MappedStatement;
15 import org.apache.ibatis.session.ResultHandler;
16 import org.apache.ibatis.session.RowBounds;
17 
18 public class SimpleStatementHandler extends BaseStatementHandler {
19 
20   //构造方法执行父类的构造方法
21   public SimpleStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
22     super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
23   }
24   
25   //执行update操作
26   public int update(Statement statement)
27       throws SQLException {
28     String sql = boundSql.getSql();
29     Object parameterObject = boundSql.getParameterObject();
30     KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
31     int rows;
32     //最终都是执行statement的getUpdateCount方法
33     if (keyGenerator instanceof Jdbc3KeyGenerator) {
34       statement.execute(sql, Statement.RETURN_GENERATED_KEYS);
35       rows = statement.getUpdateCount();
36       keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
37     } else if (keyGenerator instanceof SelectKeyGenerator) {
38       statement.execute(sql);
39       rows = statement.getUpdateCount();
40       keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
41     } else {
42       statement.execute(sql);
43       rows = statement.getUpdateCount();
44     }
45     return rows;
46   }
47   
48   //给statement添加批量处理sql语句
49   public void batch(Statement statement)
50       throws SQLException {
51     String sql = boundSql.getSql();
52     statement.addBatch(sql);
53   }
54 
55   //执行查询语句
56   public <E> List<E> query(Statement statement, ResultHandler resultHandler)
57       throws SQLException {
58     String sql = boundSql.getSql();
59     statement.execute(sql);//statement.execute方法执行sql语句
60     return resultSetHandler.<E>handleResultSets(statement);
61   }
62 
63   //构造Statement对象
64   protected Statement instantiateStatement(Connection connection) throws SQLException {
65      //通过Connection来create一个Statement对象
66     if (mappedStatement.getResultSetType() != null) {
67       return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
68     } else {
69       return connection.createStatement();
70     }
71   }
72 
73   //由于SimpleStatementHandler是处理没有参数的SQL,所以参数设置的方法无需任何处理
74   public void parameterize(Statement statement) throws SQLException {
75     // N/A
76   }
77 
78 }

可以看出主要是通过Connection创建一个Statement对象,然后通过调用Statement的execute方法执行sql语句

再看下PreparedStatementHandler,源码如下

 1 package org.apache.ibatis.executor.statement;
 2 
 3 import java.sql.Connection;
 4 import java.sql.PreparedStatement;
 5 import java.sql.ResultSet;
 6 import java.sql.SQLException;
 7 import java.sql.Statement;
 8 import java.util.List;
 9 
10 import org.apache.ibatis.executor.Executor;
11 import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
12 import org.apache.ibatis.executor.keygen.KeyGenerator;
13 import org.apache.ibatis.mapping.BoundSql;
14 import org.apache.ibatis.mapping.MappedStatement;
15 import org.apache.ibatis.session.ResultHandler;
16 import org.apache.ibatis.session.RowBounds;
17 
18 public class PreparedStatementHandler extends BaseStatementHandler {
19 
20   //执行父类构造方法
21   public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
22     super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
23   }
24 
25   //执行update操作
26   public int update(Statement statement) throws SQLException {
27     PreparedStatement ps = (PreparedStatement) statement;
28     ps.execute();
29     int rows = ps.getUpdateCount();
30     Object parameterObject = boundSql.getParameterObject();
31     KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
32     keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
33     return rows;
34   }
35 
36   //给preparedStatement对象添加批量处理sql语句
37   public void batch(Statement statement) throws SQLException {
38     PreparedStatement ps = (PreparedStatement) statement;
39     ps.addBatch();
40   }
41 
42   //执行preparedStatement的查询语句
43   public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
44     PreparedStatement ps = (PreparedStatement) statement;
45     ps.execute();
46     return resultSetHandler.<E> handleResultSets(ps);
47   }
48 
49   //构建Statement的子类PreparedStatement对象
50   protected Statement instantiateStatement(Connection connection) throws SQLException {
51     String sql = boundSql.getSql();
52     if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
53       String[] keyColumnNames = mappedStatement.getKeyColumns();
54       if (keyColumnNames == null) {
55         return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
56       } else {
57         return connection.prepareStatement(sql, keyColumnNames);
58       }
59     } else if (mappedStatement.getResultSetType() != null) {
60       return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
61     } else {
62       return connection.prepareStatement(sql);
63     }
64   }
65 
66   //给Statement对象设置参数
67   public void parameterize(Statement statement) throws SQLException {
68     parameterHandler.setParameters((PreparedStatement) statement);
69   }
70 
71 }

再看下RoutingStatementHandler,这个相当于一个StatementHandler的路由器,本身不实现任何功能,只是根据传入的参数来选择调用哪个类型的StatementHandler来处理,代码如下:

 1 public class RoutingStatementHandler implements StatementHandler {
 2 
 3 private final StatementHandler delegate;
 4 
 5 public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
 6 
 7 switch (ms.getStatementType()) {
 8 case STATEMENT:
 9 delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
10 break;
11 case PREPARED:
12 delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
13 break;
14 case CALLABLE:
15 delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
16 break;
17 default:
18 throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
19 }
20 
21 }
22 
23 @Override
24 public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
25 return delegate.prepare(connection, transactionTimeout);
26 }
27 
28 @Override
29 public void parameterize(Statement statement) throws SQLException {
30 delegate.parameterize(statement);
31 }
32 
33 @Override
34 public void batch(Statement statement) throws SQLException {
35 delegate.batch(statement);
36 }
37 
38 @Override
39 public int update(Statement statement) throws SQLException {
40 return delegate.update(statement);
41 }
42 
43 @Override
44 public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
45 return delegate.<E>query(statement, resultHandler);
46 }
47 
48 @Override
49 public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
50 return delegate.queryCursor(statement);
51 }
52 
53 @Override
54 public BoundSql getBoundSql() {
55 return delegate.getBoundSql();
56 }
57 
58 @Override
59 public ParameterHandler getParameterHandler() {
60 return delegate.getParameterHandler();
61 }
62 }

可见RoutingStatementHandler的作用就是在构造的时候根据Statement类型来创建不同的处理器,然后调用对应的处理器来进行操作。而在StatementHandler在初始化的时候,都是通过RoutingStatementHandler来进行路由的,Configuration中的创建StatementHandler代码如下:

1 public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
2 StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
3 statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
4 return statementHandler;
5 }

再看看SimpleStatementHandler是如何执行sql语句的:

1 @Override
2 protected Statement instantiateStatement(Connection connection) throws SQLException {
3 if (mappedStatement.getResultSetType() != null) {
4 return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
5 } else {
6 return connection.createStatement();
7 }
8 }

先通过Collection创建Statement对象

1 @Override
2 public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
3 String sql = boundSql.getSql();
4 statement.execute(sql);
5 return resultSetHandler.<E>handleResultSets(statement);
6 }

然后通过Statement对象执行sql语句,最后通过ResultSetHandler对象来处理执行后的结果。

原文地址:https://www.cnblogs.com/jackion5/p/9517882.html