MyBatis源码浅析(一)开篇
源码学习的好处不用多说,Mybatis源码量少、逻辑简单,将写个系列文章来学习。
SqlSession
Mybatis的使用入口位于org.apache.ibatis.session包中的SqlSession,发现它是个接口,必然有个默认实现类org.apache.ibatis.session.defaults包中的DefaultSqlSession。我们从来没有new过这个类,按照Java惯例使用SqlSessionFactory里的工厂方法。发现它也是个接口,必然有默认实现类DefaultSqlSessionFactory。该类依然不用自己创建,使用SqlSessionFactoryBuilder里的工厂方法。
DefaultSqlSession
DefaultSqlSession里主要方法:
1)Cursor<T>selectCursor(Stringstatement,Objectparameter,RowBoundsrowBounds),委托给executor.queryCursor(ms,wrapCollection(parameter),rowBounds)。
2)List<E>selectList(Stringstatement,Objectparameter,RowBoundsrowBounds)和voidselect(Stringstatement,Objectparameter,RowBoundsrowBounds,ResultHandlerhandler),委托给executor.query(ms,wrapCollection(parameter),rowBounds,handler)。
3)intupdate(Stringstatement,Objectparameter),委托给executor.update(ms,wrapCollection(parameter))。
可见,最终都有executor来完成。
Executor
Executor位于org.apache.ibatis.executor包中,是个接口,实现类是BaseExecutor和CachingExecutor。其中BaseExecutor是抽象的,有三个子类SimpleExecutor、ReuseExecutor和BatchExecutor,见名知意。BaseExecutor里主要方法:
1)List<E>query(MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler,CacheKeykey,BoundSqlboundSql)和List<E>queryFromDatabase(MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler,CacheKeykey,BoundSqlboundSql),委托为抽象的abstract<E>List<E>doQuery(MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler,BoundSqlboundSql)。
2)Cursor<E>queryCursor(MappedStatementms,Objectparameter,RowBoundsrowBounds),委托给抽象的abstract<E>Cursor<E>doQueryCursor(MappedStatementms,Objectparameter,RowBoundsrowBounds,BoundSqlboundSql)。
3)intupdate(MappedStatementms,Objectparameter),委托给抽象的abstractintdoUpdate(MappedStatementms,Objectparameter)。
基类处理公共部分,具体留给子类实现。
再看下SimpleExecutor里的主要方法:
1)List<E>doQuery(MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler,BoundSqlboundSql),委托给handler.<E>query(stmt,resultHandler)。
2)Cursor<E>doQueryCursor(MappedStatementms,Objectparameter,RowBoundsrowBounds,BoundSqlboundSql),委托给handler.<E>queryCursor(stmt)。
3)intdoUpdate(MappedStatementms,Objectparameter),委托给handler.update(stmt)。
可见,最终由handler来处理。
StatementHandler
StatementHandler位于org.apache.ibatis.executor.statement包中,是个接口,实现类是BaseStatementHandler和RoutingStatementHandler。BaseStatementHandler是抽象的,有三个子类SimpleStatementHandler、PreparedStatementHandler和CallableStatementHandler。这三个应该比较熟悉,分别处理不带参数的sql语句、参数化sql语句和存储过程。再看SimpleStatementHandler里的主要方法:
1)List<E>query(Statementstatement,ResultHandlerresultHandler),委托给statement.execute(sql)。
2)Cursor<E>queryCursor(Statementstatement),委托给statement.execute(sql)。
3)intupdate(Statementstatement),委托给statement.execute(sql)。
最终由statement执行sql。这就回到了java.sql包了。
Mybatis主要完成对sql参数的封装处理、结果集的获取并生成对象,而把sql语句的构建过程留给用户。Mybatis的作者故意这样设计的。虽然框架从整体来看是半自动的,但灵活性却得到了极大增加。