查看“入门:入门程序代码追踪”的源代码
←
入门:入门程序代码追踪
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:Mybatis]] 【2020/10/08 01:28:55】 == 入口代码 == <syntaxhighlight lang="java" line highlight="14,22,25"> public class Mybatis_first { //会话工厂 private SqlSessionFactory sqlSessionFactory; @Before public void createSqlSessionFactory() throws IOException { // mybatis配置文件 String resource = "SqlMapConfig.xml"; // 得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); // 使用SqlSessionFactoryBuilder从xml配置文件中创建SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } public void testFindUserById() { // 数据库会话实例 SqlSession sqlSession = null; try { // 创建数据库会话实例sqlSession sqlSession = sqlSessionFactory.openSession(); // selectOne查询出一条记录 User user = sqlSession.selectOne("test.findUserById", 1); </syntaxhighlight> == SqlSessionFactoryBuilder代码 == 由入口:<syntaxhighlight lang="java" inline>sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);</syntaxhighlight>: <syntaxhighlight lang="java" line highlight="7,14,29"> package org.apache.ibatis.session; public class SqlSessionFactoryBuilder { ... public SqlSessionFactory build(InputStream inputStream) { return build(inputStream, null, null); } ... public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } ... public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); } </syntaxhighlight> 得到sqlSessionFactory为'''DefaultSqlSessionFactory'''; * SqlSessionFactoryBuilder().build返回值均为DefaultSqlSessionFactory类型 == sqlSessionFactory代码 == 由入口:<syntaxhighlight lang="java" inline>sqlSession = sqlSessionFactory.openSession();</syntaxhighlight>:(由sqlSessionFactory可知,即“DefaultSqlSessionFactory.openSession()”) <syntaxhighlight lang="java" line highlight="12,19-23,34-37"> package org.apache.ibatis.session.defaults; public class DefaultSqlSessionFactory implements SqlSessionFactory { private final Configuration configuration; public DefaultSqlSessionFactory(Configuration configuration) { this.configuration = configuration; } public SqlSession openSession() { return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false); } ... private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { final Environment environment = configuration.getEnvironment(); final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); final Executor executor = configuration.newExecutor(tx, execType); return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } ... private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) { if (environment == null || environment.getTransactionFactory() == null) { return new ManagedTransactionFactory(); } return environment.getTransactionFactory(); } </syntaxhighlight> # 根据configuration得到当前环境实例environment; # 根据environment中的Transaction配置得到TransactionFactory; # 并由transactionFactory根据environment数据源配置等,创建Transaction实例(tx); ## “TransactionIsolationLevel level”:事务隔离级别 ## “boolean autoCommit”:事务自动提交【???】 # 由configuration根据tx实例和execType,创建executor实例; ## “ExecutorType execType”:executor类型(如:BatchExecutor、ReuseExecutor、SimpleExecutor) # 根据configuration, executor生成DefaultSqlSession对象,并返回; 得到sqlSession为'''DefaultSqlSession'''; * DefaultSqlSessionFactory.openSession返回值均为DefaultSqlSession类型 * 如果SqlMapConfig.xml中没有Transaction,则返回默认的'''ManagedTransactionFactory''' * tx(Transaction)作为参数,用于构造Executor * 其中Environment、TransactionFactory、Executor均被final修饰 === Executor === 由DefaultSqlSessionFactory中<syntaxhighlight lang="java" inline>configuration.getDefaultExecutorType()</syntaxhighlight>、<syntaxhighlight lang="java" inline>final Executor executor = configuration.newExecutor(tx, execType);</syntaxhighlight>: <syntaxhighlight lang="java" line highlight="5,9,21"> package org.apache.ibatis.session; public class Configuration { ... protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE; ... public ExecutorType getDefaultExecutorType() { return defaultExecutorType; } ... public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Executor executor; if (ExecutorType.BATCH == executorType) { executor = new BatchExecutor(this, transaction); } else if (ExecutorType.REUSE == executorType) { executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); } if (cacheEnabled) { executor = new CachingExecutor(executor); } executor = (Executor) interceptorChain.pluginAll(executor); return executor; } </syntaxhighlight> 得到executor = new '''SimpleExecutor'''; ==== SimpleExecutor ==== SimpleExecutor源码如下(继承了抽象类BaseExecutor): <syntaxhighlight lang="java" line highlight="13-15,37-43"> package org.apache.ibatis.executor; ... public class SimpleExecutor extends BaseExecutor { public SimpleExecutor(Configuration configuration, Transaction transaction) { super(configuration, transaction); } 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); } } 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); stmt = prepareStatement(handler, ms.getStatementLog()); return handler.<E>query(stmt, resultHandler); } finally { closeStatement(stmt); } } public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException { return Collections.emptyList(); } private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); stmt = handler.prepare(connection); handler.parameterize(stmt); return stmt; } } </syntaxhighlight> # 由configuration对象获取StatementHandler实例(handler); #: ('''StatementHandler 是四大组件中最重要的一个对象,负责操作 Statement 对象与数据库进行交流''') # 调用prepareStatement方法,初始化StatementHandler对象(handler.prepare()方法),并进行参数设置(handler.parameterize(stmt)方法); # 调用StatementHandler的执行方法(query等),并返回结果; :* doFlushStatements:刷新Statement对象(SimpleExecutor的doFlushStatements不做实质性操作) : 其中<syntaxhighlight lang="java" inline>configuration.newStatementHandler(...)</syntaxhighlight>如下: : <syntaxhighlight lang="java" line highlight="7"> package org.apache.ibatis.session; ... public class Configuration { ... 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; } </syntaxhighlight> : 可知handler为“RoutingStatementHandler”类型,其源代码如下: :: <syntaxhighlight lang="java" line highlight="9-21"> package org.apache.ibatis.executor.statement; ... 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()); } } public Statement prepare(Connection connection) throws SQLException { return delegate.prepare(connection); } public void parameterize(Statement statement) throws SQLException { delegate.parameterize(statement); } public void batch(Statement statement) throws SQLException { delegate.batch(statement); } public int update(Statement statement) throws SQLException { return delegate.update(statement); } public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { return delegate.<E>query(statement, resultHandler); } public BoundSql getBoundSql() { return delegate.getBoundSql(); } public ParameterHandler getParameterHandler() { return delegate.getParameterHandler(); } } </syntaxhighlight> :: 如同其名称一样,起到路由功能,根据Statement类型不同,使用不同的StatementHandler是实例对象去操作【???代表模式】; :: 如,“PreparedStatementHandler”其源码如下: ::: <syntaxhighlight lang="java" line highlight="25-27"> package org.apache.ibatis.executor.statement; ... public class PreparedStatementHandler extends BaseStatementHandler { public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql); } 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; } public void batch(Statement statement) throws SQLException { PreparedStatement ps = (PreparedStatement) statement; ps.addBatch(); } public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { PreparedStatement ps = (PreparedStatement) statement; ps.execute(); return resultSetHandler.<E> handleResultSets(ps); } protected Statement instantiateStatement(Connection connection) throws SQLException { 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); } } public void parameterize(Statement statement) throws SQLException { parameterHandler.setParameters((PreparedStatement) statement); } } </syntaxhighlight> :::# 与数据库的交互仍然是JDBC的API(java.sql包中); :::# 返回“resultSetHandler.<E> handleResultSets()”方法结果到,结果类型为List<Object>; :::## 返回到RoutingStatementHandler中,最终返回到BaseExecutor的List,并进行结果处理; :::## 其源代码为: :::::: <syntaxhighlight lang="java" line highlight="5"> package org.apache.ibatis.executor.resultset; ... public class DefaultResultSetHandler implements ResultSetHandler { public List<Object> handleResultSets(Statement stmt) throws SQLException { final List<Object> multipleResults = new ArrayList<Object>(); int resultSetCount = 0; ResultSetWrapper rsw = getFirstResultSet(stmt); List<ResultMap> resultMaps = mappedStatement.getResultMaps(); int resultMapCount = resultMaps.size(); validateResultMapsCount(rsw, resultMapCount); while (rsw != null && resultMapCount > resultSetCount) { ResultMap resultMap = resultMaps.get(resultSetCount); handleResultSet(rsw, resultMap, multipleResults, null); rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } String[] resultSets = mappedStatement.getResulSets(); if (resultSets != null) { while (rsw != null && resultSetCount < resultSets.length) { ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); if (parentMapping != null) { String nestedResultMapId = parentMapping.getNestedResultMapId(); ResultMap resultMap = configuration.getResultMap(nestedResultMapId); handleResultSet(rsw, resultMap, null, parentMapping); } rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } } return collapseSingleResultList(multipleResults); } </syntaxhighlight> ==== BaseExecutor ==== 抽象类BaseExecutor源码如下: <syntaxhighlight lang="java" line highlight="10,27,45,48,51,54-62,69,80-87"> package org.apache.ibatis.executor; ... public abstract class BaseExecutor implements Executor { ... public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameter); CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql); return query(ms, parameter, rowBounds, resultHandler, key, boundSql); } @SuppressWarnings("unchecked") public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId()); if (closed) throw new ExecutorException("Executor was closed."); if (queryStack == 0 && ms.isFlushCacheRequired()) { clearLocalCache(); } List<E> list; try { queryStack++; list = resultHandler == null ? (List<E>) localCache.getObject(key) : null; if (list != null) { handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); } else { list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); } } finally { queryStack--; } if (queryStack == 0) { for (DeferredLoad deferredLoad : deferredLoads) { deferredLoad.load(); } deferredLoads.clear(); // issue #601 if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) { clearLocalCache(); // issue #482 } } return list; } ... protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException; protected abstract List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException; protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException; protected void closeStatement(Statement statement) { if (statement != null) { try { statement.close(); } catch (SQLException e) { // ignore } } } ... private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { List<E> list; localCache.putObject(key, EXECUTION_PLACEHOLDER); try { list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql); } finally { localCache.removeObject(key); } localCache.putObject(key, list); if (ms.getStatementType() == StatementType.CALLABLE) { localOutputParameterCache.putObject(key, parameter); } return list; } protected Connection getConnection(Log statementLog) throws SQLException { Connection connection = transaction.getConnection(); if (statementLog.isDebugEnabled()) { return ConnectionLogger.newInstance(connection, statementLog, queryStack); } else { return connection; } } </syntaxhighlight> # “doQuery(ms, parameter, rowBounds, resultHandler, boundSql)”等方法在实现类中实现(如:BatchExecutor、ReuseExecutor、SimpleExecutor); # “getConnection(Log statementLog)”用于(使用transaction)获取链接,在SimpleExecutor的 prepareStatement 方法中调用; # “closeStatement(Statement statement)”用于关闭链接:在在SimpleExecutor的 doQuery 等方法中调用; * [[Mybatis源码:BaseExecutor解析]] === Transaction === 由DefaultSqlSessionFactory中<syntaxhighlight lang="java" inline>final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);</syntaxhighlight>及<syntaxhighlight lang="java" inline>getTransactionFactoryFromEnvironment(Environment environment)</syntaxhighlight>方法可知:<br/> <syntaxhighlight lang="java" inline>tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);</syntaxhighlight>,<br/> 即“tx = ManagedTransactionFactory.newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit)”: <syntaxhighlight lang="java" line highlight="10"> package org.apache.ibatis.transaction.managed; public class ManagedTransactionFactory implements TransactionFactory { ... public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) { // Silently ignores autocommit and isolation level, as managed transactions are entirely // controlled by an external manager. It's silently ignored so that // code remains portable between managed and unmanaged configurations. return new ManagedTransaction(ds, level, closeConnection); } } </syntaxhighlight> 得到Transaction tx = new '''ManagedTransaction''',其源码如下: : <syntaxhighlight lang="java" line highlight="25,47-55"> package org.apache.ibatis.transaction.managed; ... public class ManagedTransaction implements Transaction { private static final Log log = LogFactory.getLog(ManagedTransaction.class); private DataSource dataSource; private TransactionIsolationLevel level; private Connection connection; private boolean closeConnection; public ManagedTransaction(Connection connection, boolean closeConnection) { this.connection = connection; this.closeConnection = closeConnection; } public ManagedTransaction(DataSource ds, TransactionIsolationLevel level, boolean closeConnection) { this.dataSource = ds; this.level = level; this.closeConnection = closeConnection; } public Connection getConnection() throws SQLException { if (this.connection == null) { openConnection(); } return this.connection; } public void commit() throws SQLException { // Does nothing } public void rollback() throws SQLException { // Does nothing } public void close() throws SQLException { if (this.closeConnection && this.connection != null) { if (log.isDebugEnabled()) { log.debug("Closing JDBC Connection [" + this.connection + "]"); } this.connection.close(); } } protected void openConnection() throws SQLException { if (log.isDebugEnabled()) { log.debug("Opening JDBC Connection"); } this.connection = this.dataSource.getConnection(); if (this.level != null) { this.connection.setTransactionIsolation(this.level.getLevel()); } } } </syntaxhighlight> :# “getConnection()”在BaseExecutor的“getConnection(Log statementLog)”方法中调用; == sqlSession代码 == 以入口“User user = sqlSession.selectOne("test.findUserById", 1);”为例:<br/> 由DefaultSqlSessionFactory代码,<syntaxhighlight lang="java" inline>User user = sqlSession.selectOne("test.findUserById", 1);</syntaxhighlight>即“DefaultSqlSession.selectOne(String statement, Object parameter)”: <syntaxhighlight lang="java" line highlight="7,15,27,34"> package org.apache.ibatis.session.defaults; public class DefaultSqlSession implements SqlSession { ... public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) { this.configuration = configuration; this.executor = executor; this.dirty = false; this.autoCommit = autoCommit; } ... public <T> T selectOne(String statement, Object parameter) { // Popular vote was to return null on 0 results and throw exception on too many. List<T> list = this.<T>selectList(statement, parameter); if (list.size() == 1) { return list.get(0); } else if (list.size() > 1) { throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size()); } else { return null; } } ... public <E> List<E> selectList(String statement, Object parameter) { return this.selectList(statement, parameter, RowBounds.DEFAULT); } ... public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { try { MappedStatement ms = configuration.getMappedStatement(statement); List<E> result = executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); return result; } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } </syntaxhighlight> * selectOne也是由selectList实现,“list.size() > 1”则抛出异常 * 操作数据库由executor实现 * 默认的executor是“SimpleExecutor” *: (继承自抽象类BaseExecutor):
返回至“
入门:入门程序代码追踪
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息