做精酿啤酒购买的网站,中国十大热门网站排名,什么网站做的好,普宁建设局网站后面开始分析sql执行的源码流程也就是这一部分
一、factory.openSession()
重点关注configuration.newExecutor这个方法#xff0c;获取事务处理器比较简单#xff0c;就是获取一个jdbc的事务管理器。
这个方法通过传入的执行器类型来创建不同的执行器#xff0c;有simp…后面开始分析sql执行的源码流程也就是这一部分
一、factory.openSession()
重点关注configuration.newExecutor这个方法获取事务处理器比较简单就是获取一个jdbc的事务管理器。
这个方法通过传入的执行器类型来创建不同的执行器有simple、batch、reuse等如果支持缓存的话会创建CachingExecutor执行器
执行完成之后最后生成了一个DefaultSqlSession有关DefaultSqlSession特别要注意一点它是一个非线程安全的类。 二、获取mapper接口
关于knownMappers前面讲过是一个map里面存放的是mapper的类型和MapperProxyFactory类。
后面就是调用mapperProxyFactory.newInstance(sqlSession)进行mapper接口的实例化。最终会拿着mapper接口、代理方法缓存 生成InvokeHandler用来生成Jdk代理必须要的类当调用被代理的方法的时候会调用到InvokeHandler的invokde方法最终返回的代理对象就是下图所示 三、处理查询操作
当我们调用这个查询方法的时候最终会调用到userProxy的invoke方法先看cachedInvoker方法最终会生成一个PlainMethodInvoker这个类是MapperProxy的静态内部类这里会调用到mapperMethod.execute方法 MapperMethod中command存放的是sql的一些信息method存放方法的一些信息
public class MapperMethod {// todo 存放sql的一些信息其中name属性存放的是“包名、类名、方法名”private final SqlCommand command;// todo 方法的签名主要存放方法的一些信息private final MethodSignature method;public MapperMethod(Class? mapperInterface, Method method, Configuration config) {this.command new SqlCommand(config, mapperInterface, method);this.method new MethodSignature(config, mapperInterface, method);}public Object execute(SqlSession sqlSession, Object[] args) {Object result;switch (command.getType()) {case INSERT: {Object param method.convertArgsToSqlCommandParam(args);result rowCountResult(sqlSession.insert(command.getName(), param));break;}case UPDATE: {Object param method.convertArgsToSqlCommandParam(args);result rowCountResult(sqlSession.update(command.getName(), param));break;}case DELETE: {Object param method.convertArgsToSqlCommandParam(args);result rowCountResult(sqlSession.delete(command.getName(), param));break;}case SELECT:// todo 处理查询操作if (method.returnsVoid() method.hasResultHandler()) {executeWithResultHandler(sqlSession, args);result null;} else if (method.returnsMany()) {// todo 返回多行记录result executeForMany(sqlSession, args);} else if (method.returnsMap()) {result executeForMap(sqlSession, args);} else if (method.returnsCursor()) {result executeForCursor(sqlSession, args);} else {Object param method.convertArgsToSqlCommandParam(args);result sqlSession.selectOne(command.getName(), param);if (method.returnsOptional() (result null || !method.getReturnType().equals(result.getClass()))) {result Optional.ofNullable(result);}}break;case FLUSH:result sqlSession.flushStatements();break;default:throw new BindingException(Unknown execution method for: command.getName());}if (result null method.getReturnType().isPrimitive() !method.returnsVoid()) {throw new BindingException(Mapper method command.getName() attempted to return null from a method with a primitive return type ( method.getReturnType() ).);}return result;}在execute方法里面会处理 sql 的 INSERTmapper.xml 中的 insert 标签、UPDATEmapper.xml 中的 update 标签、DELETEmapper.xml 中的 delete 标签、SELECTmapper.xml 中的 select 标签、FLUSH针对 BatchExecutor 执行器执行缓存的 Statement等操作这里我们仅关注 select 操作接下来调用DefaultSqlSession.selectList方法来执行这里会从configuration里面通过接口对应的MappedStatement通过执行器调用执行由于我们默认设置了一级缓存所以会执行到CacheingExecutor.query方法这个delegate.query最终调用的是SimpleExecutor.query方法最终会执行到simpleExecutor.doQuery方法
四、总结
本文主要介绍了 mybatis 执行 sql 的流程介绍的内容如下
mybatis 的 sql 执行操作方法在 SqlSession 中SqlSession 是 mybatis 的执行入口XxxMapper 是一个接口mybatis 基于 jdk 动态代理机制会生成一个代理对象其 InvocationHandler具体类为 MapperProxy的 invoker(…) 方法会获取 mapper.xml 定义的 sql 并执行执行 XxxMapper 方法时实际调用的是 MapperProxy#invoker(…) 方法整个方法的执行过程中会获取 mapper.xml 中的 sql 语句然后使用执行器SimpleExecutor、ReuseExecutor、BatchExecutor 等处理 sql 的执行mybatis 提供的 DefaultSqlSession 是非线程安全的想要线程安全可以使用 SqlSessionManager