架构图如下
关键的类
- SqlSession
Mybatis暴露给用户的最顶层接口,内部集成了数据库的增删改查操作以及执行操作的执行器,这个类的实例是不能被多线程共享的,因此在spring中每一次访问service都会新建一个Sqlsession。主要的功能为找到apperStatement然后生成BoundSql动态sql,最后交给statementHandle执行这个sql语句。 - Configuration
配置信息存储类,将XML的配置信息加载到内存中并以属性的方式存储到这个类中,其中Mapper相关的存储在MapperRegister类中,当要获取Mapper时通过MapperRegister的newProxyInstance动态代理模式获取到mapper - StatementHandler
封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。 - ParameterHandler
负责对用户传递的参数转换成JDBC Statement 所需要的参数 - ResultSetHandler
负责将JDBC返回的ResultSet结果集对象转换成List类型的集合 - TypeHandler
负责java数据类型和jdbc数据类型之间的映射和转换 - MappedStatement
MappedStatement维护了一条<select|update|delete|insert>节点的封装,初始化Configurtion时,将Mapper文件的节点封装成一个Entry键值对,键为statementId,值为MappedStatement - BoundSql
动态sql信息,由MapperStatement得到
Mybatis流程分析
public static void main(String[] args) throws Exception{
SqlSessionFactory factory =
new SqlSessionFactoryBuilder().
build(Resources
.getResourceAsReader("configuration.xml"));
SqlSession sqlSession = factory.openSession();
UserDao userMapper = sqlSession.getMapper(UserDao.class);
List<User> users = userMapper.findUserById(1);
System.out.println(users);
}
- 通过XML文件,构建configuration对象,后使用建造者模式构建 SqlSessionFactory 对象
- 通过工厂模式拿到defaultSqlSession对象。
- 获取到mapper接口的代理模式生成的对象。表面上是从sqlsession中获取的,实际上他通过
sqlsession->
configuration->
MapperRegister->
mapperProxyFactory反射+代理获取到mapper
我们注意到,mapperProxy的构造函数里还是传入了sqlsession,因此每一个mapper都是与一个sqlsession绑定的。 - 那么mapper的执行又是如何执行的呢?因为代理模式使用的是JDK的动态代理,因此我们需要找到这个代理的invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
try {
return method.invoke(this, args);
} catch (Throwable var5) {
throw ExceptionUtil.unwrapThrowable(var5);
}
} else {
MapperMethod mapperMethod = this.cachedMapperMethod(method);
return mapperMethod.execute(this.sqlSession, args);
}
}
可以看出invoke是调用了mapperMethod的execute方法,我们分析这个mapperMethod易得知,他其实又调用回了sqlsession的增删改差的方法。并传入了当前的statementId,也就是namespace+方法名
- 任务到达sqlSession之后,sqlSession通过statementId生成MapperStatement,又得到BoundSql
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
// 1.根据具体传入的参数,动态地生成需要执行的SQL语句,用BoundSql对象表示
BoundSql boundSql = ms.getBoundSql(parameter);
// 2.为当前的查询创建一个缓存Key
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
- 之后通过StatementHandler处理,statement使用paramterHandle与ResultHandle分别注入参数与对结果进行处理,最后通过生产的preparestatement或者statement进行增删改查。
框架支持层
1. 事务管理机制
主要分为2种,分别为交给jdbc管理的与交给容器管理的。其实就是对事务的管理的规则。容器主要为spring,spring主要对事务的传播机制和事务隔离级别进行了限制,这两点可以参考 spring事务传播机制与事务隔离级别总结