内容简介:映射器的本质是生成动态代理对象新版本的至今没找到....这里直接使用DefaultSqlSession类做说明
映射器的本质是生成动态代理对象
新版本的至今没找到....
这里直接使用DefaultSqlSession类做说明
编写的 工具 类
public static SqlSession openSqlSesion(){ // 判空处理 if(sqlSessionFactory == null){ initSqlSessionFactory(); } return sqlSessionFactory.openSession(); }
进入openSession可以发现这是一个接口
public interface SqlSessionFactory { SqlSession openSession(); SqlSession openSession(boolean autoCommit); SqlSession openSession(Connection connection); SqlSession openSession(TransactionIsolationLevel level); SqlSession openSession(ExecutorType execType); SqlSession openSession(ExecutorType execType, boolean autoCommit); SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level); SqlSession openSession(ExecutorType execType, Connection connection); Configuration getConfiguration(); }
新类使用的是SqlSessionManager
@Override public SqlSession openSession() { return sqlSessionFactory.openSession(); }
其sqlSessionFactory如下
可以发现这是一个单例
private SqlSessionManager(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance( SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionInterceptor()); }
采取类加载机制,类加载进入内存当中
加载进入的如下几个
public static SqlSessionManager newInstance(Reader reader) { return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, null)); } public static SqlSessionManager newInstance(Reader reader, String environment) { return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, environment, null)); } public static SqlSessionManager newInstance(Reader reader, Properties properties) { return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, properties)); } public static SqlSessionManager newInstance(InputStream inputStream) { return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, null, null)); } public static SqlSessionManager newInstance(InputStream inputStream, String environment) { return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, environment, null)); } public static SqlSessionManager newInstance(InputStream inputStream, Properties properties) { return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, null, properties)); } public static SqlSessionManager newInstance(SqlSessionFactory sqlSessionFactory) { return new SqlSessionManager(sqlSessionFactory); }
采用的是
new SqlSessionFactoryBuilder().build(reader, null, null)
对于builder来说如下
public SqlSessionFactory build(Reader reader, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } }
可以看到是一个配置类
然后进入return
可以发现进入
private final Configuration configuration;
进入配置类
public class Configuration {
所有的配置文件信息都在这里,并且生成的保存配置文件的对象也会保存为此类实例化的对象.
第581行可以看到这是个执行器
执行器
public Executor newExecutor(Transaction transaction) { return newExecutor(transaction, 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; }
这就是SqlSession下的第一个对象,生成执行器的方法.
执行器是用于执行 Java 和数据库交互的东西
根据源码可以看到有三种执行器
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); }
这是三种执行器
executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
这两句是根据配置文件读取内容
这一句是
interceptorChain.pluginAll(executor)
为配置文件,并且将会执行配置插件的代码
可以在这里看下这个方法
executor = new SimpleExecutor(this, transaction);
可以看一下执行SimpleExecutor的代码
/** * Copyright 2009-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ibatis.executor; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.Collections; import java.util.List; import org.apache.ibatis.cursor.Cursor; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.logging.Log; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.transaction.Transaction; /** * @author Clinton Begin */ public class SimpleExecutor extends BaseExecutor { public SimpleExecutor(Configuration configuration, Transaction transaction) { super(configuration, transaction); } @Override 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); } } @Override 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.query(stmt, resultHandler); } finally { closeStatement(stmt); } } @Override protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException { Configuration configuration = ms.getConfiguration(); StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql); Statement stmt = prepareStatement(handler, ms.getStatementLog()); stmt.closeOnCompletion(); return handler.queryCursor(stmt); } @Override public List<BatchResult> doFlushStatements(boolean isRollback) { return Collections.emptyList(); } private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); stmt = handler.prepare(connection, transaction.getTimeout()); handler.parameterize(stmt); return stmt; } }
这一个是执行查询的方法
@Override 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.query(stmt, resultHandler); } finally { closeStatement(stmt); } }
MyBatis会根据配置文件构建StatementHandler
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
再次调用prepareStatement(handler, ms.getStatementLog());对配置文件的 SQL 进行编译并进行初始化
prepareStatement(handler, ms.getStatementLog());
最后通过这一句执行查询
handler.query(stmt, resultHandler);
其中会构建出newStatementHandler
该执行器的作用是用来调度处理数据库会话器,参数处理器,结果处理器等
数据库会话器
数据库会话器用于处理数据库会话的
继续回到配置类中
即
/** * @author Clinton Begin */ 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; }
其是一个实现了StatementHandler接口的实例化的RoutingStatementHandler的对象
然后查看该类
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()); } }
这是一个数据库会话器,定义了一个
private final StatementHandler delegate;
这里采用的是适配器模式
用来根据配置文件生成对应的StatementHandler对象,然后给所有的生成该类的,提供一个简易的适配器
这个适配器为一个简易的接口
/** * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ibatis.executor.statement; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.List; import org.apache.ibatis.cursor.Cursor; import org.apache.ibatis.executor.parameter.ParameterHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.session.ResultHandler; /** * @author Clinton Begin */ public interface StatementHandler { Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException; void parameterize(Statement statement) throws SQLException; void batch(Statement statement) throws SQLException; int update(Statement statement) throws SQLException; <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException; <E> Cursor<E> queryCursor(Statement statement) throws SQLException; BoundSql getBoundSql(); ParameterHandler getParameterHandler(); }
该接口有以上方法
生成对象的,并实现了该接口的类为SimpleStatementHandler所以进入该SimpleStatementHandler类
最重要的三个方法,prepare, parameterize, query
由于该类已经继承了,所以应当进入BaseStatementHandler类
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException { ErrorContext.instance().sql(boundSql.getSql()); Statement statement = null; try { statement = instantiateStatement(connection); setStatementTimeout(statement, transactionTimeout); 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); } }
其中instantiateStatement方法是对
SQL进行预编译,超时,获取最大行数
执行器再次会调用
@Override public void parameterize(Statement statement) { // N/A }
我也不知道为什么会是N/A
这里以查询为例子,会调度到
@Override public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { String sql = boundSql.getSql(); statement.execute(sql); return resultSetHandler.handleResultSets(statement); }
由于执行器都已经编译完成,参数都已经加入了进去,所以了resultSetHandler.handleResultSets(statement) 对执行的参数和结果进行返回
这里的一条SQL执行流程就熟悉了.
数据库的执行器会生成StatementHandler对象,然后调用prepare方法,该prepare方法,会调用instantiateStatement对sql进行预编译,然后在调用parameterize对参数设置,最后控制器再调度到query,进行查询,获取sql,进行执行,最后返回结果
参数处理器
在上方代码中可以看到执行器是通过参数处理器parameterize进行参数处理的
@Override public void parameterize(Statement statement) throws SQLException { parameterHandler.setParameters((PreparedStatement) statement); }
继续查看初始化的参数
protected final ParameterHandler parameterHandler;
进入该接口
/** * Copyright 2009-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ibatis.executor.parameter; import java.sql.PreparedStatement; import java.sql.SQLException; /** * A parameter handler sets the parameters of the {@code PreparedStatement}. * * @author Clinton Begin */ public interface ParameterHandler { Object getParameterObject(); void setParameters(PreparedStatement ps) throws SQLException; }
其中MyBatis的实现类为
public class DefaultResultSetHandler implements ResultSetHandler
这个是参数处理设置
@Override 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 | SQLException e) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } } } } }
结果处理器
对于ResuSetHandler来说有如下几个
/** * @author Clinton Begin */ public interface ResultSetHandler { <E> List<E> handleResultSets(Statement stmt) throws SQLException; <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException; void handleOutputParameters(CallableStatement cs) throws SQLException; }
以上所述就是小编给大家介绍的《SqlSession四大对象》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- OC对象的本质 实例对象,类对象,元类对象
- 可迭代对象,迭代器(对象),生成器(对象)
- 重学前端学习笔记(七)--JavaScript对象:面向对象还是基于对象?
- Webform 内置对象 Session对象、Application全局对象,ViewState详细介绍
- 对象.原型链,函数.原型对象
- Java 对象组成,对象头分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JavaScript权威指南
弗拉纳根 / 东南大学出版社 / 2007-6 / 99.00元
《JavaScript权威指南(影印版)(第5版)》已经经过全面地修订和扩展,涵盖了构建当今Web2.0应用程序所需的JavaScript技术。《JavaScript权威指南(影印版)(第5版)》不仅是一本实例驱动的程序员指南,同时也是一本可以摆在桌边随时查阅的参考手册,它以全新的章节阐述了有效使用Javascript脚本所需要知道的一切,包括: 脚本化的HTTP和Ajax;XML处理;使用......一起来看看 《JavaScript权威指南》 这本书的介绍吧!