源碼學習的好處不用多說,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(String statement, Object parameter, RowBounds rowBounds),委托給executor.queryCursor(ms, wrapCollection(parameter), rowBounds)。
- 2)List<E> selectList(String statement, Object parameter, RowBounds rowBounds)和void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler),委托給executor.query(ms, wrapCollection(parameter), rowBounds, handler)。
- 3)int update(String statement, Object parameter),委托給executor.update(ms, wrapCollection(parameter))。
可見,最終都有executor來完成。
Executor
Executor位於org.apache.ibatis.executor包中,是個介面,實現類是BaseExecutor和CachingExecutor。其中BaseExecutor是抽象的,有三個子類SimpleExecutor、ReuseExecutor和BatchExecutor,見名知意。BaseExecutor里主要方法:
- 1)List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)和List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql),委托為抽象的abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)。
- 2)Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds),委托給抽象的abstract <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql)。
- 3)int update(MappedStatement ms, Object parameter),委托給抽象的abstract int doUpdate(MappedStatement ms, Object parameter)。
基類處理公共部分,具體留給子類實現。再看下SimpleExecutor里的主要方法:
- 1)List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql),委托給handler.<E>query(stmt, resultHandler)。
- 2)Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql),委托給handler.<E>queryCursor(stmt)。
- 3)int doUpdate(MappedStatement ms, Object parameter),委托給handler.update(stmt)。
可見,最終由handler來處理。
StatementHandler
StatementHandler位於org.apache.ibatis.executor.statement包中,是個介面,實現類是BaseStatementHandler和RoutingStatementHandler。BaseStatementHandler是抽象的,有三個子類SimpleStatementHandler、PreparedStatementHandler和CallableStatementHandler。這三個應該比較熟悉,分別處理不帶參數的sql語句、參數化sql語句和存儲過程。再看SimpleStatementHandler里的主要方法:
- 1)List<E> query(Statement statement, ResultHandler resultHandler),委托給statement.execute(sql)。
- 2)Cursor<E> queryCursor(Statement statement),委托給statement.execute(sql)。
- 3)int update(Statement statement),委托給statement.execute(sql)。
最終由statement執行sql。這就回到了java.sql包了。
Mybatis主要完成對sql參數的封裝處理、結果集的獲取並生成對象,而把sql語句的構建過程留給用戶。Mybatis的作者故意這樣設計的。雖然框架從整體來看是半自動的,但靈活性卻得到了極大增加。