MyBatis核心部件
- SqlSession 作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能;
- Executor MyBatis执行器,调度核心,负责SQL语句的生成和查询缓存维护;
- StatementHandler 封装了JDBC Statement操作,负责对JDBC statement的操作,如设置参数,将Statement结果转化为list集合
- ParameterHandler 负责对用户传递的参数转换成JDBC Statement所需要的参数
- ResultSetHandler 负责将JDBC返回的ResultSet结果集对象转换成list类型的集合
- TypeHandler 负责java数据类型和jdbc数据类型之间的映射和转换
- MappedStatement MappedStatement维护了一条<select|update|delete|insert>节点的封装
- SqlSource 负责根据用户传递的parameterObject,动态生成SQL语句,将信息封装到BoundSql对象中并返回
- BoundSql 表示动态生成的SQL语句以及相应的参数信息
- Configuration MyBatis所有的配置信息都维护在Configuration对象中;
Mybatis 生命周期
1.init SqlSessionFactory
根据mybatis-config加载sqlsessionfactorybuilder
init XMLConfigBuilder
XPathParser
DocumentBuilderFactory DocumentBuilder
2.SqlSessionFactory.openSession
3.getMapper
存储Mapper信息的是HashMap
key Class
value MapperProxyFactory
mapperInterface methodCache
根据代理信息动态生成一个代理类
4.执行sql业务
execute
通过switch (insert,update,delete,select) DefaultSqlSession -- selectOne 以接口名+方法名为id获取mappedStatement(Map<String,MappedStatement>)
5.sqlsession -- close
执行器 close 判断是否需要回滚事务 关闭游标 errorcontext -- reset
带着问题看源码
- 问题1 mybatis调用过程
1.调用mapper代理类获取MapperMethod 2.MapperMethod.execute -> 根据sql行为关键字->select->判断使用select里面的不同分支调用SqlSession.selectone 3.DefaultSqlSession.selectList->从configuration获取MappedStatement 4.执行器executor调用query,mappedStatement作为参数 5.此时执行器为cachingExecutor(包装了baseExecutor),此处关键函数delegate.createCacheKey加载这条sql的缓存key 5.5.如果这里localCache有缓存结果时调用handleLocallyCachedOutputParameters 6.调用baseExecutor.queryFromDatabase-->doQuery 7.StatementHandler嗲用query(代理输出日志打印sql参数是在PreparedStatementLogger中打印) 8.调用jdbc连接数据库获取结果由ClientPreparedStatement,并且调用时会加jdbc的互斥锁 9.PrepareQuery.fillSendPacket --> 填充请求数据 -->调用executeInternal 10.返回结果存储在clientpreparedstatement-->results内 11.获取到结果后先removeCache再缓存
问题2什么时候初始化mapper
初始化XMLConfigBuilder 容器(HashMap --> )
configuration.MapperRegistry --> ResolverUtil.find() 根据包名找出需要加载的接口
while(hasNext)方式遍历加载Mapper configuration.MapperRegistry.addMappers