mybatis执行流程
2023-05-05 21:52:17 6 举报
mybatis查询流程
作者其他创作
大纲/内容
一级缓存不为null
根据CommandType不同(SELECT、INSERT。。执行不同逻辑)
直接调用Executor执行器的底层query方法查询
如果Configuration启用了缓存(默认为true),则将Executor封装成CachingExecutor
获取到返回结果,session.close()
通过type(包名),在knowsMappers中获取MapperProxyFactory
根据返回的Properties设置vfsImpl字段
直接调用Method.invoke方法动态代理生成对象
MapperProxy实现了InvocationHandler类
获取方法返回类型和方法参数的传入顺序,进行初始化并赋值
根据解析后返回的Configuration对象构建SqlSessionFactoryBuilder
handleLocallyCachedOutputParameters针对存储过程调用的处理在一级缓存命中时,获取缓存中保存的输出类型参数,并设置到用户传入的实参对象中,
通过ResultSetHandler处理结果集(返回的结果集是字节数组,将字节数组进行转换)的映射
inputStream = Resources.getResourceAsStream(resource)
检测处理行数是否达到上限,并且ResultSet.next是否为null
获取Configuration对象
获取settings标签name和value属性节点,并将值封装成Properties类返回
如果没有注解且只有一个参数
获取标签下resultType、resultMap、parameterMap等所有信息,并封装到MappedStatement中
如果不是
检测是否需要自动映射
创建事务工厂(TransactionFactory)和数据源工厂(DataSourceFactory)
遍历List<UnMappedColumnAutoMapping>将metaObject中类成员变量进行赋值,返回SQL查询需要的Java类(此时metaObject就已经是完整的要返回的Java对象,其中类变量都有根据SQL查出来的具体值)
不存在
非嵌套查询,并且select节点配置的flushCache属性为true时,清空一级缓存
根据标签确定SqlCommandType(供6种类型,还有UNKNOW和FLUS)
执行具体SQL查询
将事务工厂和DB工厂封装进Environment(构造者模式)对象,并设置在Configuration中
getMapper(),通过动态代理加载对象
为null
applyAutomaticMappings()自动映射
根据返回的Object对象,创建MetaObject对象
数组形式也同理
handleRowValues处理行数据
根据Environment类创建TransactionFactory,为null则默认ManagedTransactionFactory,通过Factory创建Transaction
如果ms为null,有@FLUSH处理@FLUSH,没有则抛异常
根据StatementType创建不同的StatementHandler(最终都会返回RoutingStatementHandler类型)
减少queryStack查询层数
解析mappers属性节点
调用XMLConfigBuilder中XPathParser对XML文件进行解析
是否存在嵌套ResultMap的情况(例如collection标签)
增加queryStack查询层数
根据返回结果集get(0),获取实际返回数据
将method和PlainMethodInvoker放入methodCache并返回PlainMethodInvoke
创建Executor执行器,共三种类型,默认为SimpleExecutor(类中有一级缓存的变量)
存在
Mybatis-config.xml中所有节点属性
获取resultMap集合并遍历
selectOne(),单独查询一条记录,底层也会调用selectList()方法,不过会get(0)返回第一条,结果为null,则返回null
创建XMLMapperEntityResolver对象,指定了XML文件规范,相当于将DTD封装成一个对象
executor.query(),调用执行器来执行查询
加载
解析前的准备工作
通过MapperProxyFactory获取具体MapperProxy代理类
调用doQuery方法执行数据库查询
构建MapperMethod,并为SqlCommand和MethodSignature赋值
获取标签中属性,如果不存在,记录在Configuration中typeAlias集合
根据JDK1.8和JDK1.9分别实现并构建不同的DefaultMethodInvoker
通过handler.prepare()创建Statement对象(设置超时时间、读取条数等)
创建configuration对应的MetaClass对象,并检测Configuration中是否定义了key指定属性的setter方法
返回的PlainMethodInvoker实现了MapperMethodInvoker,PlainMethodInvoker类中invoke()会调用execute()
methodCache中没有
将创建的XMLMapperEntityResolver对象作为参数用来构建XPathParser,用来解析XML
handleResultSet()方法中对结果集处理parentMapping是否为null
如果用户未指定resultHandler,则使用DefaultResultHandler作为默认的resultHandler对象
创建SqlSessionFactoryBuilder解析xml文件
解析environments属性节点
封装整个运行过程中需要的参数,有些属性有默认值,有些属性后期再修改
在localCache中添加占位符EXECUTION_PLACEHOLDER,key为CacheKey
返回List<UnMappedColumnAutoMapping>其中包含了Java实体对象类变量名、DB列名、还有类变量对应的类型
获取mapper下所有select、update、delete、insert标签,循环解析
根据返回的MapperMethod对象构建PlainMethodInvoker(包含具体的sql语句、方法返回值、参数等)
根据类全限定名+方法名获取MappedStatement
Statement.execute(),执行sql查询
从xml文件中configuration节点开始、,逐层遍历,每个属性详细解析,并将解析的值设置到Configuration对应属性中
到上面为止mybatis-config.xml文件已经加载解析完成
处理占位符,完成参数绑定到TypeHandler中(此时已经将sql中参数替换为实参,sql已经完整,可以执行)
获取XML文件中properties标签中url或resource属性节点,并将值封装成Properties类放入Configuration中
获取第一个ResultSet对象,封装ResultSetWrapper类(ResultSetWrapper中包含了sql查询返回的实体对象的列属性和对应的Java类型)
1.创建XPath对象2.将XML转成Document对象
执行MapperProxy类中invoke方法来完成具体方法的调用
将结果集加到list中返回,selectList的get(0)就是从这个list中获取的
如果是resource、url或class属性(三者互斥),则再次构建XMLMapperBuilder类,获取属性中文件,转换成流进行xml文件解析,放入knowMappers中
1.构建SqlCommand
将查询结果和CacheKey放入localCache
如果是多个参数
select查询会根据返回类型不同做不同逻辑处理
mybatis-config.xml
如果是Object类型
method.convertArgsToSqlCommandParam处理参数
查询一级缓存
parseConfiguration(parser.evalNode(\"/configuration\"))
不为null
handleRowValuesForNestedResultMap嵌套结果处理
如果没有参数,返回null
根据CacheKey删除占位符
根据分页信息,计算偏移量
handler中封装了configuration、executor、mappedStatement等多个类
XMLConfigBuilder通过构造方法进行对象的创建,同时会对全局变量类Configuration进行初始化
创建XMLConfigBuilder对象,此对象parse()会返回全局配置类Configuration,Configuration作为参数用来构建SqlSessionFactory
如果ms不为null,获取查询类型type(SqlCommandType中的一种)和全限定名+方法名组成的name,封装进SqlCommand
没开启二级缓存
createResultObject()创建返回的Java对象(类变量都为为null),返回Object
根据type(包名)获取到对应的mapper.xml配置文件并再次构建XMLMapperBuilder进行解析
获取具体执行SQL语句和参与映射关系,构建BoundSql并返回
getRowValue() 获取一行的值
将全限定名+方法名组成的id、分页、具体SQL、方法参数等更新到CacheKey中,
开启二级缓存
获取typeAliases标签下的package或alias标签节点
调用Proxy.newProxyInstance()方法完成对象创建(JDK动态代理)
将全限定名+方法名组成的id、分页、具体SQL、方法参数等更新到缓存中,
一级缓存为null
如果是接口中普通的抽象方法
构建CacheKey
获取结果集ResultSet
2.构建MethodSignature
遍历names,并将参数名和具体实参做映射放到map中,并且同时会生成一个参数前缀(param),会按照param1、param2的形式,对应实参放入map中
处理多结果集中的嵌套映射
查询层数为0(所有嵌套查询等都已经完成)
根据类全限定名+具体方法名,获取MapperStatement对象
execute()方法
通过Configuration中transcation创建数据库连接
如果参数不是集合形式,则直接返回
如果接口方法是default修饰
handleRowValuesForSimpleResultMap单一结果处理
根据SqlSessionFactoryBuilder获取SqlSession对象(封装Transcation和Executor)
收藏
收藏
0 条评论
回复 删除
下一页