MYBATIS执行流程
Mybatis的主要成员 Configuration MyBatis所有的配置信息 都保存在Configuration对象中,配置文件中的大部分配置都会 存储到该类中
SqlSession 作为MyBatis工作的主要顶层API,表示和数据库交互时的会话,完成必要数据库增删改查功能
根据statement id,在mybatis配置对象configuration 中获取到对应的mappedstatement 对象,然后调用执行器来执行具体操作
Executor MyBatis执行器,是MyBatis调度的核心,负责sql语句的生成和查询缓存的维护
根据传递的参数,完成sql语句的动态解析,生成BoundSql对象,供StatementHandler使用
为查询创建缓存,以提高性能
创建JDBC的Statement链接对象,传递给StatementHandler对象,返回List查询结果
StatementHandler 封装了JDBC Statement操作,负责对JDBC statement的操作,如设置参数等
1. 对于JDBC的preparedStatement类型的对象,创建过程中,sql语句字符串会包含若干个?占位符,然后再赋值。
2. StatementHandler通过parameterize(statement)方法对statement进行设值
StatementHandler通过List query(Statement statement,ResultHandler resultHandler)方法来完成执行Statement,和将Statement对象返回的resultSet封装成List
ParameterHandler 负责对用户传递的参数转换成JDBC Statement所对应的数据类型,对statement对象的?占位符进行赋值
ResultSetHandler 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
TypeHandler 负责java数据类型和jdbc数据类型(也可以说是数据表列类型)之间的映射和转换
MappedStatement MappedStatement维护一条<select|update|delete|insert>节点的封装
SqlSource 负责根据用户传递的parameterObject,动态的生成SQL语句,将信息封装到BoundSql对象中并返回
BoundSql 表示动态生成的SQL语句以及相应的参数信息
源码解析 SqlSession类
SqlSession位于mybatis包的org.apache.ibatis.session目录下,字面意思就是sql的会话,用于程序和数据库直接的sql会话,程序执行一次数据库操作就需要创建一个sqlSession,操作结束即关闭sqlSession;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 public interface SqlSession extends Closeable { <T> T selectOne (String statement) ; <T> T selectOne (String statement, Object parameter) ; <E> List<E> selectList (String statement) ; <E> List<E> selectList (String statement, Object parameter) ; <E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds) ; <K, V> Map<K, V> selectMap (String statement, String mapKey) ; <K, V> Map<K, V> selectMap (String statement, Object parameter, String mapKey) ; <K, V> Map<K, V> selectMap (String statement, Object parameter, String mapKey, RowBounds rowBounds) ; <T> Cursor<T> selectCursor (String statement) ; <T> Cursor<T> selectCursor (String statement, Object parameter) ; <T> Cursor<T> selectCursor (String statement, Object parameter, RowBounds rowBounds) ; void select (String statement, Object parameter, ResultHandler handler) ; void select (String statement, ResultHandler handler) ; void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) ; int insert (String statement) ; int insert (String statement, Object parameter) ; int update (String statement) ; int update (String statement, Object parameter) ; int delete (String statement) ; int delete (String statement, Object parameter) ; void commit () ; void commit (boolean force) ; void rollback () ; void rollback (boolean force) ; List<BatchResult> flushStatements () ; @Override void close () ; void clearCache () ; Configuration getConfiguration () ; <T> T getMapper (Class<T> type) ; Connection getConnection () ; }
SqlSession中的方法全是和数据库相关的增删改查以及事务的提交方法。
sqlSession有三个实现类,除了默认的DefaultSqlSession之外,还有SqlSessionManager和SqlSessionTemplate
DefaultSqlSession类 类结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public class DefaultSqlSession implements SqlSession { private final Configuration configuration; private final Executor executor; private final boolean autoCommit; private boolean dirty; private List<Cursor<?>> cursorList; public DefaultSqlSession (Configuration configuration, Executor executor, boolean autoCommit) { this .configuration = configuration; this .executor = executor; this .dirty = false ; this .autoCommit = autoCommit; } public DefaultSqlSession (Configuration configuration, Executor executor) { this (configuration, executor, false ); } }
查询单条数据
很明显selectOne的方法最终都是调用了selectList方法,然后取唯一的一条数据返回。那在看看selectList相关的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @Override public <T> T selectOne (String statement) { return this .selectOne(statement, null ); } @Override public <T> T selectOne (String statement, Object parameter) { List<T> list = this .selectList(statement, parameter); if (list.size() == 1 ) { return list.get(0 ); } else if (list.size() > 1 ) { throw new TooManyResultsException ("Expected one result (or null) to be returned by selectOne(), but found: " + list.size()); } else { return null ; } }
查询列表数据
共有三个selectList方法,最终都是调用了最后一个selectList方法,这里有三个参数:statement是sql语句;parameter是传入的参数;RowBounds是和分页相关的参数
最终调用的是executor.query的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 @Override public <E> List<E> selectList (String statement) { return this .selectList(statement, null ); } @Override public <E> List<E> selectList (String statement, Object parameter) { return this .selectList(statement, parameter, RowBounds.DEFAULT); } @Override public <E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds) { try { MappedStatement ms = configuration.getMappedStatement(statement); return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
RowBounds类
该类不推荐使用,因为RowBounds类是内存分页推荐使用物理分页
RowBounds的两个属性:offSet是指查询数据时从多少位置开始查询,limit是指返回数据的条数,默认是从0位置开始查询到Integer的最大值,相关于默认是不做分页处理;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class RowBounds { public static final int NO_ROW_OFFSET = 0 ; public static final int NO_ROW_LIMIT = Integer.MAX_VALUE; public static final RowBounds DEFAULT = new RowBounds (); private final int offset; private final int limit; public RowBounds () { this .offset = NO_ROW_OFFSET; this .limit = NO_ROW_LIMIT; } public RowBounds (int offset, int limit) { this .offset = offset; this .limit = limit; } public int getOffset () { return offset; } public int getLimit () { return limit; } }
insert、update、delete方法
SqlSession的insert和delete的方法最终都是调用了update方法,而update方法最终也是调用了Executor的update
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 @Override public int insert (String statement) { return insert(statement, null ); } @Override public int insert (String statement, Object parameter) { return update(statement, parameter); } @Override public int update (String statement) { return update(statement, null ); } @Override public int update (String statement, Object parameter) { try { dirty = true ; MappedStatement ms = configuration.getMappedStatement(statement); return executor.update(ms, wrapCollection(parameter)); } catch (Exception e) { throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } @Override public int delete (String statement) { return update(statement, null ); } @Override public int delete (String statement, Object parameter) { return update(statement, parameter); }
核心代码
sqlSession虽然叫程序和数据库之间的SQL会话,但是它并没有具体去执行sql语句,最终的sql语句的执行是由执行器Executor执行的,而SqlSession的作用只是创建了MappedStatement对象以及调用执行器去执行SQL,他的commit、rollback方法同样最终都是调用的执行器Executor的对应的方法
1 2 3 4 MappedStatement ms = configuration.getMappedStatement(statement);return executor.update(ms, wrapCollection(parameter));