增加源码分析-insert()

---------------------------------------------------------------------

public int insert(String statement, Object parameter) {         //statement就是传进来的要调用xml定义的哪个sql语句,parameter就是调用语句需要传进来的参数对象
return update(statement, parameter);
}

---------------------------------------------------------------------

进入到update方法中

public int update(String statement, Object parameter) {
try {
dirty = true;                         //
MappedStatement ms = configuration.getMappedStatement(statement);    //configuration通过传进来的参数,获取对应的映射statement
return executor.update(ms, wrapCollection(parameter));            //executor是个代理对象
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}

---------------------------------------------------------------

进入到invoke方法中

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {       //参数中的method是Executor.update
try {

//获取声明的方法集[Executor.query],这个集合是自己在mybatis配置文件plugin节点下定义的要拦截的方法集
Set<Method> methods = signatureMap.get(method.getDeclaringClass()); 
if (methods != null && methods.contains(method)) {              // methods.contains(method)==false
return interceptor.intercept(new Invocation(target, method, args));
}

//target是CachingExecutor类型的,其中有两个参数SimpleExecutor的delegate和TransactionalCacheManager类型的tcm

//args是Object数组,[0]=MappedStatement,[1]=Employee(上面update方法传进来的参数)
return method.invoke(target, args);        //交给target所指定的方法继续执行程序           
} catch (Exception e) {
throw ExceptionUtil.unwrapThrowable(e);
}
}

----------------------------------------------------------------

public int update(MappedStatement ms, Object parameterObject) throws SQLException {
flushCacheIfRequired(ms);                            //如果有缓存,则清除。
return delegate.update(ms, parameterObject);
}

-----------------------------------------------------------

public int update(MappedStatement ms, Object parameter) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
if (closed) throw new ExecutorException("Executor was closed.");
clearLocalCache();              //清除本地缓存
return doUpdate(ms, parameter);
}

---------------------------------------------------------------------------------------------------------

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); //这里新建一个statement处理程序
stmt = prepareStatement(handler, ms.getStatementLog());  //statement准备阶段,获取到有关数据库的信息等
return handler.update(stmt);
} finally {
closeStatement(stmt);
}
}

------------------------------newStatementHandler具体执行过程-------------------------------------------------------------------------------------------------------

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;

}

------------------------

public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {

switch (ms.getStatementType()) {                            //PREPARED(默认)
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 PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}

---------------------------

protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;

this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();

if (boundSql == null) { // issue #435, get the key before calculating the statement
generateKeys(parameterObject);
boundSql = mappedStatement.getBoundSql(parameterObject);    //获取boundSql
}

this.boundSql = boundSql;

this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);  //参数处理器
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);//结果处理器
}

------------------真正执行插入的核心代码在PreparedStatementHandler类中------------------------

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;                          //返回执行的结果
}

-----------------------------------------------------------------------------------------------------

修改源码分析--update()同增加操作

删除源码分析--delete()同update()操作

public int delete(String statement, Object parameter) {
return update(statement, parameter);
}

查询源码分析--selectList()

public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);        //获取到对应的ms
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();
}
}

-------------------------------------------------------------------

public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameterObject);                          //获取到boundSql
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);                //执行查询
}

---------------------------------------------------------------------------------------------

public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
throws SQLException {
Cache cache = ms.getCache();                //首先获取缓存
if (cache != null) {                      //如果缓存不为空,清除缓存
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, parameterObject, boundSql);
@SuppressWarnings("unchecked")
List<E> list = (List<E>) tcm.getObject(cache, key);
if (list == null) {
list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578. Query must be not synchronized to prevent deadlocks
}
return list;
}
}
return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

------------------------------------------------------------------------------------------

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;
}

Mybatis 源码分析--crud的更多相关文章

  1. 【MyBatis源码分析】select源码分析及小结

    示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...

  2. Mybatis源码分析-BaseExecutor

    根据前文Mybatis源码分析-SqlSessionTemplate的简单分析,对于SqlSession的CURD操作都需要经过Executor接口的update/query方法,本文将分析下Base ...

  3. Mybatis源码分析-StatementHandler

    承接前文Mybatis源码分析-BaseExecutor,本文则对通过StatementHandler接口完成数据库的CRUD操作作简单的分析 StatementHandler#接口列表 //获取St ...

  4. MyBatis源码分析-MyBatis初始化流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  5. MyBatis源码分析-SQL语句执行的完整流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  6. MyBatis源码分析(5)——内置DataSource实现

    @(MyBatis)[DataSource] MyBatis源码分析(5)--内置DataSource实现 MyBatis内置了两个DataSource的实现:UnpooledDataSource,该 ...

  7. MyBatis源码分析(4)—— Cache构建以及应用

    @(MyBatis)[Cache] MyBatis源码分析--Cache构建以及应用 SqlSession使用缓存流程 如果开启了二级缓存,而Executor会使用CachingExecutor来装饰 ...

  8. MyBatis源码分析(3)—— Cache接口以及实现

    @(MyBatis)[Cache] MyBatis源码分析--Cache接口以及实现 Cache接口 MyBatis中的Cache以SPI实现,给需要集成其它Cache或者自定义Cache提供了接口. ...

  9. MyBatis源码分析(2)—— Plugin原理

    @(MyBatis)[Plugin] MyBatis源码分析--Plugin原理 Plugin原理 Plugin的实现采用了Java的动态代理,应用了责任链设计模式 InterceptorChain ...

随机推荐

  1. linux命令格式及基础命令(一)

    linux命令格式 ~]#COMMAND [选项] [参数] 例如: ~]#ls 不带任何选项和参数 ``` stylus ~]#ls -lh /etc 列出/etc下所有文件和目录,同时要求以格式和 ...

  2. linux进程通信之使用匿名管道进行父子进程通信

    管道:是指用于连接一个读进程和一个写进程,以实现它们之间通信的共享文件,又称pipe文件. 管道是单向的.先进先出的.无结构的.固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起 ...

  3. IIS 7.5最新解析漏洞

    IIS7.5解析漏洞 http://www.cnk0n9.com/fckeditor/editor/fckeditor.html, 上传图片,浏览,上传一个aspx的一句话木马,名字为:a.aspx. ...

  4. JavaScipt 事件体系

    事件机制 jQuery对事件的绑定分别有几个API .bind()/.live()/.delegate()/.on() 不管是用什么方式绑定,归根到底还是用addEventListener/attac ...

  5. spring.net 配置文件需要注意换行问题

    今天在做Spring.NET Demo时写配置文件写ObjectNames 节点的Value成这样 <object id="ProxyCreator" type=" ...

  6. SAP SE11 网格布局显示

    SE11 进入数据显示界面后 在  Settings -> User Parameters,  Data Browser 页面 勾选ALV Grid display 即可.

  7. 关于ADO.NET 超时的问题

    前几天超时问题困扰我很头疼. 为什么我设置了链接字符串的超时时间很长,可是等了一小会就报错Timeout了? connectionString="Data Source=.;Initial ...

  8. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(六)

    前言 在接下来的篇幅里将对系统的模块功能进行编写.主要以代码实现为主.这一篇我们需要完成系统模块“角色管理”的相关功能.完成后可以对系统框架结构有进一步了解. Abstract层 之前说过,Abstr ...

  9. 一个crackme的分析

    是看雪合集的一个,因为老师让我们多练习,所以我就找了个crackme来练习 http://images2015.cnblogs.com/blog/638600/201612/638600-201612 ...

  10. 计划任务,机器码与注册码,Web服务

    01.计划任务的客户端配置 TScheduleTask 辅助结构内容: TScheduleRecord<ScheduleTask.pas> TScheduleRecord.Schedule ...