测试方法:
@Test
public void test01() throws IOException {
//1.根据xml配置文件(全局配置文件)创建一个SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession session = sqlSessionFactory.openSession();
try {
EmployeeMapper employeeMapper= session.getMapper(EmployeeMapper.class);
Employee emp = employeeMapper.getEmpById(1);
System.out.println(emp);
session.clearCache();
Employee emp2 = employeeMapper.getEmpById(2);
System.out.println(emp2);
System.out.println(emp==emp2);
} finally {
session.close();
}
}
private SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
给mapper的查询方法打上断点,执行。发现方法最终执行的是MapperProxy的invoke方法,先执行Object类的方法,在执行cachedMapperMethod方法,返回一个MapperMethod类,然后执行MapperMethod的execute方法
因为我设置查询方法且直接返回了对象,所以执行到selectOne方法
而selectOne执行的还是selectList,然后获取了第一个元素并返回
selectList最后由executor去执行query,因为我这里开启了二级缓存,所以这里executor是CachingExecutor
query方法:先创建BoundSql,其中包含sql语句,查询参数等,然后创建一个CacheKey作为二级缓存的key
执行了delegate的query方法,而这个delegate是SimpleExecutor
我们去看queryFromDatabase方法
doQuery方法,先去获取configuration,再根据configuration创建statementHandler,点击进去
在newStatementHandler方法中,期间会被插件拦截器拦截处理
跳出方法,点击prepareStatement方法,与编译产生statement对象,
handler.parameterize(stmt):预编译sql,产生preparedStatement对象
在BaseStatementHandler中设置了ParameterHandler和ResultSetHandler,这两个方法同样会被插件拦截器拦截处理。
在DefaultParameterHandler中使用类型处理器(TypeHandler)设置sql参数
在SimpleStatementHandler中执行query查询sql,并使用resultSetHandler处理查询结果
resultSetHandler处理流程后面就不看了,比较复杂,不过最后还是由TypeHandler处理返回值类型。
查询流程总结:
注意:四大对象:Executor,StatementHandler,ParameterHandler,ResultSetHandler在创建的时候,都会被插件拦截器拦截。