ibatis学习四执行流程浅析

      首先看一段最基本的ibatis执行代码

1 public static void main(String[] args) throws IOException, SQLException{
2         String config = "ibatis/SqlMapConfig.xml";
3         Reader reader = Resources.getResourceAsReader(config);
4         SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
5         List<Product> list = sqlMap.queryForList("getProductInfo", 1);
6         for(Product product : list){
7             System.out.println(product);
8         }
9     }

      首先使用Resources读取配置文件信息返回给reade,Resources的相关源码

 1 public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
 2     InputStream in = null;
 3     if (loader != null) in = loader.getResourceAsStream(resource);
 4     if (in == null) in = ClassLoader.getSystemResourceAsStream(resource);
 5     if (in == null) throw new IOException("Could not find resource " + resource);
 6     return in;
 7   }
 8 
 9 public static Reader getResourceAsReader(String resource) throws IOException {
10     Reader reader;
11     if (charset == null) {
12       reader = new InputStreamReader(getResourceAsStream(resource));
13     } else {
14       reader = new InputStreamReader(getResourceAsStream(resource), charset);
15     }
16     
17     return reader;
18   }

      就是调用Resources的静态方法getResourceAsReader,该方法调用getResourceAsStream方法,ClassLoader根据配置文件的路径返回InputStream,找不到文件则抛出异常。getResourceAsReader方法根据返回的InputStream返回Reader,若指定了编码类型则转换为相应编码。

      SqlMapClientBuilder类的buildSqlMapClient方法代码

1 public static SqlMapClient buildSqlMapClient(Reader reader) {
2 //    return new XmlSqlMapClientBuilder().buildSqlMap(reader);
3     return new SqlMapConfigParser().parse(reader);
4   }

      SqlMapConfigParser类根据配置文件解析参数返回

      下面看一下ibatis内部SqlMapClient的实现过程。

      SqlMapClientImpl的部分代码

 1 public class SqlMapClientImpl implements SqlMapClient, ExtendedSqlMapClient {
 2 
 3   private static final Log log = LogFactory.getLog(SqlMapClientImpl.class);
 4 
 5   /**
 6    * Delegate for SQL execution
 7    */
 8   public SqlMapExecutorDelegate delegate;
 9 
10   protected ThreadLocal localSqlMapSession = new ThreadLocal();
11 
12   /**
13    * Constructor to supply a delegate
14    *
15    * @param delegate - the delegate
16    */
17   public SqlMapClientImpl(SqlMapExecutorDelegate delegate) {
18     this.delegate = delegate;
19   }
20 
21 
22 protected SqlMapSessionImpl getLocalSqlMapSession() {
23     SqlMapSessionImpl sqlMapSession = (SqlMapSessionImpl) localSqlMapSession.get();
24     if (sqlMapSession == null || sqlMapSession.isClosed()) {
25       sqlMapSession = new SqlMapSessionImpl(this);
26       localSqlMapSession.set(sqlMapSession);
27     }
28     return sqlMapSession;
29   }
30 
31   public List queryForList(String id, Object paramObject) throws SQLException {
32     return getLocalSqlMapSession().queryForList(id, paramObject);
33   }
34 
35   public List queryForList(String id) throws SQLException {
36     return getLocalSqlMapSession().queryForList(id);
37   }
38 
39   public List queryForList(String id, Object paramObject, int skip, int max) throws SQLException {
40     return getLocalSqlMapSession().queryForList(id, paramObject, skip, max);
41   }
42 
43   public List queryForList(String id, int skip, int max) throws SQLException {
44     return getLocalSqlMapSession().queryForList(id, skip, max);
45   }
46 }

      由代码中看出,ThreadLocal 的localSqlMapSession中存储着SqlMapSessionImpl实例,queryForList方法实际是使用本线程内的SqlMapSessionImpl的queryForList方法。

      SqlMapSessionImpl的部分代码

 1 public class SqlMapSessionImpl implements SqlMapSession {
 2 
 3   protected SqlMapExecutorDelegate delegate;
 4   protected SessionScope sessionScope;
 5   protected boolean closed;
 6 
 7   /**
 8    * Constructor
 9    *
10    * @param client - the client that will use the session
11    */
12   public SqlMapSessionImpl(SqlMapClientImpl client) {
13     this.delegate = client.getDelegate();
14     this.sessionScope = this.delegate.beginSessionScope();
15     this.sessionScope.setSqlMapClient(client);
16     this.sessionScope.setSqlMapExecutor(client);
17     this.sessionScope.setSqlMapTxMgr(client);
18     this.closed = false;
19   }
20 
21 public List queryForList(String id, Object paramObject) throws SQLException {
22     return delegate.queryForList(sessionScope, id, paramObject);
23   }
24 
25   public List queryForList(String id) throws SQLException {
26     return queryForList(id, null);
27   }
28 
29   public List queryForList(String id, Object paramObject, int skip, int max) throws SQLException {
30     return delegate.queryForList(sessionScope, id, paramObject, skip, max);
31   }
32 
33   public List queryForList(String id, int skip, int max) throws SQLException {
34     return queryForList(id, null, skip, max);
35   }
36 }
37 
38   

      SqlMapSessionImpl中有一个delegate代理,它的queryForList方法中调用delegate的queryForList方法。

      SqlMapExecutorDelegate类比较复杂,它实现了执行数据库操作的完整环境,包括缓存、MappedStatement、参数映射ParameterMap、返回结果ResultMap、事务管理、增删改成操作。源代码有900+行,只给出部分代码,完整代码参考ibatis源码包中SqlMapExecutorDelegate.java文件。

 1 public class SqlMapExecutorDelegate {
 2 
 3   private static final Probe PROBE = ProbeFactory.getProbe();
 4 
 5   private boolean lazyLoadingEnabled;
 6   private boolean cacheModelsEnabled;
 7   private boolean enhancementEnabled;
 8   private boolean useColumnLabel = true;
 9   private boolean forceMultipleResultSetSupport;
10 
11   private TransactionManager txManager;
12 
13   private HashMap mappedStatements;
14   private HashMap cacheModels;
15   private HashMap resultMaps;
16   private HashMap parameterMaps;
17 
18   protected SqlExecutor sqlExecutor;
19   private TypeHandlerFactory typeHandlerFactory;
20   private DataExchangeFactory dataExchangeFactory;
21   
22   private ResultObjectFactory resultObjectFactory;
23   private boolean statementCacheEnabled;
24 
25   /**
26    * Default constructor
27    */
28   public SqlMapExecutorDelegate() {
29     mappedStatements = new HashMap();
30     cacheModels = new HashMap();
31     resultMaps = new HashMap();
32     parameterMaps = new HashMap();
33 
34     sqlExecutor = new SqlExecutor();
35     typeHandlerFactory = new TypeHandlerFactory();
36     dataExchangeFactory = new DataExchangeFactory(typeHandlerFactory);
37   }
38 
39  public List queryForList(SessionScope sessionScope, String id, Object paramObject) throws SQLException {
40     return queryForList(sessionScope, id, paramObject, SqlExecutor.NO_SKIPPED_RESULTS, SqlExecutor.NO_MAXIMUM_RESULTS);
41   }
42 
43 public List queryForList(SessionScope sessionScope, String id, Object paramObject, int skip, int max) throws SQLException {
44     List list = null;
45 
46     MappedStatement ms = getMappedStatement(id);
47     Transaction trans = getTransaction(sessionScope);
48     boolean autoStart = trans == null;
49 
50     try {
51       trans = autoStartTransaction(sessionScope, autoStart, trans);
52 
53       StatementScope statementScope = beginStatementScope(sessionScope, ms);
54       try {
55         list = ms.executeQueryForList(statementScope, trans, paramObject, skip, max);
56       } finally {
57         endStatementScope(statementScope);
58       }
59 
60       autoCommitTransaction(sessionScope, autoStart);
61     } finally {
62       autoEndTransaction(sessionScope, autoStart);
63     }
64 
65     return list;
66   }
67 }

      获取sessionScope、statementScope、MappedStatement、Transaction等相关实例,核心是调用MappedStatement的executeQueryForList方法:list = ms.executeQueryForList(statementScope, trans, paramObject, skip, max);

      查看一下MappedStatement相关代码

 1 public class MappedStatement {
 2   private String id;
 3   private Integer resultSetType;
 4   private Integer fetchSize;
 5   private ResultMap resultMap;
 6   private ParameterMap parameterMap;
 7   private Class parameterClass;
 8   private Sql sql;
 9   private int baseCacheKey;
10   private SqlMapClientImpl sqlMapClient;
11   private Integer timeout;
12   private ResultMap[] additionalResultMaps = new ResultMap[0];
13   private List executeListeners = new ArrayList();
14   private String resource;
15 
16 public List executeQueryForList(StatementScope statementScope, Transaction trans, Object parameterObject, int skipResults, int maxResults)
17       throws SQLException {
18     try {
19       DefaultRowHandler rowHandler = new DefaultRowHandler();
20       executeQueryWithCallback(statementScope, trans.getConnection(), parameterObject, null, rowHandler, skipResults, maxResults);
21       return rowHandler.getList();
22     } catch (TransactionException e) {
23       throw new NestedSQLException("Error getting Connection from Transaction.  Cause: " + e, e);
24     }
25   }
26 
27 protected void executeQueryWithCallback(StatementScope statementScope, Connection conn, Object parameterObject, Object resultObject, RowHandler rowHandler, int skipResults, int maxResults)
28       throws SQLException {
29     ErrorContext errorContext = statementScope.getErrorContext();
30     errorContext.setActivity("preparing the mapped statement for execution");
31     errorContext.setObjectId(this.getId());
32     errorContext.setResource(this.getResource());
33 
34     try {
35       parameterObject = validateParameter(parameterObject);
36 
37       Sql sql = getSql();
38 
39       errorContext.setMoreInfo("Check the parameter map.");
40       ParameterMap parameterMap = sql.getParameterMap(statementScope, parameterObject);
41 
42       errorContext.setMoreInfo("Check the result map.");
43       ResultMap resultMap = sql.getResultMap(statementScope, parameterObject);
44 
45       statementScope.setResultMap(resultMap);
46       statementScope.setParameterMap(parameterMap);
47 
48       errorContext.setMoreInfo("Check the parameter map.");
49       Object[] parameters = parameterMap.getParameterObjectValues(statementScope, parameterObject);
50 
51       errorContext.setMoreInfo("Check the SQL statement.");
52       String sqlString = sql.getSql(statementScope, parameterObject);
53 
54       errorContext.setActivity("executing mapped statement");
55       errorContext.setMoreInfo("Check the SQL statement or the result map.");
56       RowHandlerCallback callback = new RowHandlerCallback(resultMap, resultObject, rowHandler);
57       sqlExecuteQuery(statementScope, conn, sqlString, parameters, skipResults, maxResults, callback);
58 
59       errorContext.setMoreInfo("Check the output parameters.");
60       if (parameterObject != null) {
61         postProcessParameterObject(statementScope, parameterObject, parameters);
62       }
63 
64       errorContext.reset();
65       sql.cleanup(statementScope);
66       notifyListeners();
67     } catch (SQLException e) {
68       errorContext.setCause(e);
69       throw new NestedSQLException(errorContext.toString(), e.getSQLState(), e.getErrorCode(), e);
70     } catch (Exception e) {
71       errorContext.setCause(e);
72       throw new NestedSQLException(errorContext.toString(), e);
73     }
74   }
75 }
protected void sqlExecuteQuery(StatementScope statementScope, Connection conn, String sqlString, Object[] parameters, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException {
    getSqlExecutor().executeQuery(statementScope, conn, sqlString, parameters, skipResults, maxResults, callback);
  }

      最终由SqlExecutor实现sql操作,实现代码

 1 /**
 2    * Long form of the method to execute a query
 3    *
 4    * @param statementScope     - the request scope
 5    * @param conn        - the database connection
 6    * @param sql         - the SQL statement to execute
 7    * @param parameters  - the parameters for the statement
 8    * @param skipResults - the number of results to skip
 9    * @param maxResults  - the maximum number of results to return
10    * @param callback    - the row handler for the query
11    * @throws SQLException - if the query fails
12    */
13   public void executeQuery(StatementScope statementScope, Connection conn, String sql, Object[] parameters, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException {
14     ErrorContext errorContext = statementScope.getErrorContext();
15     errorContext.setActivity("executing query");
16     errorContext.setObjectId(sql);
17     PreparedStatement ps = null;
18     ResultSet rs = null;
19     setupResultObjectFactory(statementScope);
20     try {
21       errorContext.setMoreInfo("Check the SQL Statement (preparation failed).");
22       Integer rsType = statementScope.getStatement().getResultSetType();
23       if (rsType != null) {
24         ps = prepareStatement(statementScope.getSession(), conn, sql, rsType);
25       } else {
26         ps = prepareStatement(statementScope.getSession(), conn, sql);
27       }
28       setStatementTimeout(statementScope.getStatement(), ps);
29       Integer fetchSize = statementScope.getStatement().getFetchSize();
30       if (fetchSize != null) {
31         ps.setFetchSize(fetchSize.intValue());
32       }
33       errorContext.setMoreInfo("Check the parameters (set parameters failed).");
34       statementScope.getParameterMap().setParameters(statementScope, ps, parameters);
35       errorContext.setMoreInfo("Check the statement (query failed).");
36       ps.execute();
37       errorContext.setMoreInfo("Check the results (failed to retrieve results).");
38 
39       // Begin ResultSet Handling
40       rs = handleMultipleResults(ps, statementScope, skipResults, maxResults, callback);
41       // End ResultSet Handling
42     } finally {
43       try {
44         closeResultSet(rs);
45       } finally {
46         closeStatement(statementScope.getSession(), ps);
47       }
48     }
49 
50   }

      handleMuiltipleResults方法代码

 1 private ResultSet handleMultipleResults(PreparedStatement ps, StatementScope statementScope, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException {
 2     ResultSet rs;
 3     rs = getFirstResultSet(statementScope, ps);
 4     if (rs != null) {
 5       handleResults(statementScope, rs, skipResults, maxResults, callback);
 6     }
 7 
 8     // Multiple ResultSet handling
 9     if (callback.getRowHandler() instanceof DefaultRowHandler) {
10       MappedStatement statement = statementScope.getStatement();
11       DefaultRowHandler defaultRowHandler = ((DefaultRowHandler) callback.getRowHandler());
12       if (statement.hasMultipleResultMaps()) {
13         List multipleResults = new ArrayList();
14         multipleResults.add(defaultRowHandler.getList());
15         ResultMap[] resultMaps = statement.getAdditionalResultMaps();
16         int i = 0;
17         while (moveToNextResultsSafely(statementScope, ps)) {
18           if (i >= resultMaps.length) break;
19           ResultMap rm = resultMaps[i];
20           statementScope.setResultMap(rm);
21           rs = ps.getResultSet();
22           DefaultRowHandler rh = new DefaultRowHandler();
23           handleResults(statementScope, rs, skipResults, maxResults, new RowHandlerCallback(rm, null, rh));
24           multipleResults.add(rh.getList());
25           i++;
26         }
27         defaultRowHandler.setList(multipleResults);
28         statementScope.setResultMap(statement.getResultMap());
29       } else {
30         while (moveToNextResultsSafely(statementScope, ps)) ;
31       }
32     }
33     // End additional ResultSet handling
34     return rs;
35   }
原文地址:https://www.cnblogs.com/waimai/p/2847460.html