码迷,mamicode.com
首页 > 其他好文 > 详细

mybatis源码解析5---StatementHandler解析

时间:2018-08-22 17:12:35      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:执行   error   pre   封装对象   过程   lse   ble   cat   ppi   

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 }

 

 

 

是 

mybatis源码解析5---StatementHandler解析

标签:执行   error   pre   封装对象   过程   lse   ble   cat   ppi   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!