源碼學習的好處不用多說,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的作者故意這樣設計的。雖然框架從整體來看是半自動的,但靈活性卻得到了極大增加。