mybatis的运行流程
一、原生用法
1. 构建SqlSessionFactory
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
在SqlSessionFactoryBuilder中,首先解析配置文件,得到Configuration,然后build new一个SqlSessionFactory返回:
build
看一下parse中具体做了哪些工作:
parse
mapperElement中会把解析出来的Mapper放到MapperRegistry中,以便后续使用。
2. 创建SqlSession
try (SqlSession session = sqlSessionFactory.openSession()) {
Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
}
最终委托到DefaultSqlSessionFactory的openSessionFromDataSource:
创建SqlSession
之后,一个集齐了executor,configuration的SqlSession就创建好了。
3. 创建Mapper
看一下SqlSession里getMapper的具体实现:
getMapper
委托给configuration后又委托给了mapperRegistry:
mapperRegistry
在第一步创建SqlSessionFactory的最后说过,在parse中会解析xml中的mapper并放入mapperRegistry中,现在就是取出来构建实例的时候了。并且传入了sqlSession,这样后续mapper中就可以把具体操作委托给sqlSession去完成。
MapperProxyFactory
MapperProxy
接着就可以看到这里到了真正创建Mapper的时机,也看到Mapper的实现类MapperProxy,通过动态代理的方式创建出来。我们知道动态代理最终的方法会委托给InvocationHandler里,进到MapperProxy看一下,果不其然:
MapperProxy
最后在mapperMethod中,不出意外肯定会委托给sqlSession执行:
MapperMethod
好了,先到这里,后续在分析在SqlSession中的执行过程。
二、让Spring管理一切
1. SqlSessionFactoryBean
把SqlSessionFactory注入到spring容器中
@Configuration
public class MyBatisConfig {
@Bean
public SqlSessionFactory sqlSessionFactory() {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
return factoryBean.getObject();
}
}
2. SqlSession同理
@Configuration
public class MyBatisConfig {
@Bean
public SqlSessionTemplate sqlSession() throws Exception {
return new SqlSessionTemplate(sqlSessionFactory());
}
}
现在已经获得了和原生用法中一样的效果,并且更进一步,可以以注入的方式使用SqlSession了。
3. Mapper
实际使用中,显然不可能通过SqlSessionTemplate一个一个去getMapper,都是通过spring管理,直接注入使用。那么必然有地方把Mapper都加载起来纳入Spring管理。以@MapperScan为例分析其过程如下。
在MapperScannerRegistrar中,借助spring的能力扫描满足条件的mapper,并将其注入容器。具体参考https://blog.csdn.net/elim168/article/details/88131712
doScan
到这里已经可以看到,往spring容器里注入了mapper,class是MapperFactoryBean,对于FactoryBean,spring创建bean的时候会调用其getObject方法,进入MapperFactoryBean看一下
MapperFactoryBean
Ok,这样就和原生用法中的分析一致,回到了SqlSession的getMapper。
一路看下来,我们可以看出来,引入spring-mybatis,其实就是把原来需要我们手动去操作mybatis的地方全部以spring的方式管理起来,我们只管用注入的方式去使用Mapper就好了。
三、SqlSession如何操作数据库
selectMapperStatement从configuration中获取,最初在解析xml的时候会一并解析存入。
然后交给executor执行,executor出现在openSessionFromDataSource时,默认类型是SimpleExecutor。继续跟踪,进入到基类BaseExecutor中:
BaseExecutor
首先从cache中提取,如果没有就进入queryFromDatabase,queryFromDatabase中又回到了Executor实现类的doQuery:
doQuery
在newStatementHandler中会把plugin插进去,prepareStatement会拿到一个connection,并编译statement,也就是使用jdbc时需要的那些操作,最后交由handler执行:
PreparedStatementHandler
这里默认的就是PreparedStatementHandler,也就是预编译PreparedStatement。
mybatis架构
mybatis主要构件对照图2
mybatis架构设计
网友评论