mybatis源码阅读(一):SqlSession和SqlSessionFactory
轉(zhuǎn)載自??mybatis源碼閱讀(一):SqlSession和SqlSessionFactory?
一、接口定義
????聽名字就知道這里使用了工廠方法模式,SqlSessionFactory負(fù)責(zé)創(chuàng)建SqlSession對象。其中開發(fā)人員最常用的就是DefaultSqlSession
(1)SqlSession接口定義
public interface SqlSession extends Closeable {// 泛型方法,參數(shù)表示使用的查詢SQL語句,返回值為查詢的結(jié)果對象<T> T selectOne(String statement);// 第二個(gè)參數(shù)表示需要用戶傳入的實(shí)參,也就是SQL語句綁定的實(shí)參<T> T selectOne(String statement, Object parameter);// 查詢結(jié)果集有多條記錄,會封裝成結(jié)果對象列表返回<E> List<E> selectList(String statement);<E> List<E> selectList(String statement, Object parameter);// 第三個(gè)參數(shù)用于限制解析結(jié)果集的范圍<E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);/**** selectMap 方法的原理和參數(shù)都與selectList方法類型,但結(jié)果集會被映射成Map對象返回* 其中mapKey參數(shù)指定了結(jié)果集哪一列作為map的key,其他參數(shù)同上*/<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);// 返回值是游標(biāo)對象,參數(shù)同上<T> Cursor<T> selectCursor(String statement);<T> Cursor<T> selectCursor(String statement, Object parameter);<T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds);// 查詢的結(jié)果對象將由此處指定的handler對象處理,其余參數(shù)同上void select(String statement, Object parameter, ResultHandler handler);void select(String statement, ResultHandler handler);void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);// 執(zhí)行insert語句int insert(String statement);int insert(String statement, Object parameter);// 執(zhí)行update語句int update(String statement);int update(String statement, Object parameter);// 執(zhí)行deleteint delete(String statement);int delete(String statement, Object parameter);// 提交事務(wù)void commit();void commit(boolean force);// 事務(wù)回滾void rollback();void rollback(boolean force);// 將請求刷新到數(shù)據(jù)庫List<BatchResult> flushStatements();// 關(guān)閉當(dāng)前session@Overridevoid close();// 清空session 緩存void clearCache();// 獲取Configuration 對象Configuration getConfiguration();// 獲取type 對象的Mapper對象<T> T getMapper(Class<T> type);// 獲取該Sqlsession 對象的數(shù)據(jù)庫連接Connection getConnection(); }SqlSession數(shù)據(jù)庫的C、R、U、D及事務(wù)處理接口,你懂的。
(2)SqlSessionFactory
public interface SqlSessionFactory {SqlSession openSession();SqlSession openSession(boolean autoCommit);SqlSession openSession(Connection connection);SqlSession openSession(TransactionIsolationLevel level);SqlSession openSession(ExecutorType execType);SqlSession openSession(ExecutorType execType, boolean autoCommit);SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);SqlSession openSession(ExecutorType execType, Connection connection);Configuration getConfiguration(); }這個(gè)大家也都懂的
SqlSession實(shí)現(xiàn)類:DefaultSqlSession和SqlSessionManager
SqlSessionFactory實(shí)現(xiàn)類:DefaultSqlSessionFactory和SqlSessionManager
(3)DefaultSqlSession
@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 <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();} }這里主要看這兩個(gè)方法,因?yàn)閐elete和insert最終執(zhí)行掉用的都是update方法,查詢就更不用說了。從代碼上看都是從configuration對象中獲取MappedStatement 對象 然后把事情交給小弟Executor去執(zhí)行,這里用了很典型的策略設(shè)計(jì)模式,這個(gè)關(guān)于Executor 后面介紹。
(4)DefaultSqlSessionFactory
/*** 通過數(shù)據(jù)源獲取數(shù)據(jù)庫連接,并創(chuàng)建Executor以及DefaultSqlSession對象*/ private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {Transaction tx = null;try {final Environment environment = configuration.getEnvironment();final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);final Executor executor = configuration.newExecutor(tx, execType);return new DefaultSqlSession(configuration, executor, autoCommit);} catch (Exception e) {closeTransaction(tx); // may have fetched a connection so lets call close()throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);} finally {ErrorContext.instance().reset();} }/*** 用戶提供數(shù)據(jù)庫連接對象,使用該數(shù)據(jù)庫連接對象創(chuàng)建Executor和DefaultSqlSession對象*/ private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {try {boolean autoCommit;try {autoCommit = connection.getAutoCommit();} catch (SQLException e) {// Failover to true, as most poor drivers// or databases won't support transactionsautoCommit = true;} final Environment environment = configuration.getEnvironment();final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);final Transaction tx = transactionFactory.newTransaction(connection);final Executor executor = configuration.newExecutor(tx, execType);return new DefaultSqlSession(configuration, executor, autoCommit);} catch (Exception e) {throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);} finally {ErrorContext.instance().reset();} }DefaultSqlSessionFactory主要提供了兩種創(chuàng)建DefaultSqlSession對象的方式,一種是通過數(shù)據(jù)源獲取數(shù)據(jù)庫連接,并創(chuàng)建Executor以及DefaultSqlSession對象,另一種是用戶提供數(shù)據(jù)庫連接對象,使用該數(shù)據(jù)庫連接對象創(chuàng)建Executor和DefaultSqlSession對象。
(5)SqlSessionManager
SqlSessionManager同時(shí)實(shí)現(xiàn)SqlSession接口和SqlSessionFactory接口,也就是同時(shí)提供了創(chuàng)建SqlSession對象以及SqlSession對象操作數(shù)據(jù)庫的功能。SqlSessionManager與DefaultSqlSessionFactory的主要不同點(diǎn)是SqlSessionManager提供了兩種模式,一種是和DefaultSqlSessionFactory的行為相同,同一線程每次訪問數(shù)據(jù)庫就都會創(chuàng)建新的DefaultSqlSession,第二種是通過ThreadLocal變量記錄當(dāng)前線程的SqlSession對象,避免同一線程多次創(chuàng)建SqlSession對象。至于使用動態(tài)代理的目的,是為了通過攔截器InvocationHandler,增強(qiáng)目標(biāo)target的方法調(diào)用。
private final SqlSessionFactory sqlSessionFactory; // SqlSession的代理對象 會使用JDK的動態(tài)代理方式實(shí)現(xiàn) private final SqlSession sqlSessionProxy;/*** ThreadLocal 變量,記錄一個(gè)與當(dāng)前線程綁定的SqlSession對象* localSqlSession 中記錄的SqlSession對象的代理對象,在SqlSessionManager初始化的時(shí)候*/ private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<SqlSession>(); /*** SqlSessionManager 的私有構(gòu)造方法*/ private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;// 使用動態(tài)代理生成SqlSession的代理對象this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(),new Class[]{SqlSession.class},new SqlSessionInterceptor()); }/*** 通過newInstance方法創(chuàng)建SqlSessionManager對象* @param reader* @return*/public static SqlSessionManager newInstance(Reader reader) {return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, null));} // 內(nèi)部類 private class SqlSessionInterceptor implements InvocationHandler {public SqlSessionInterceptor() {// Prevent Synthetic Access}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 獲取當(dāng)前線程綁定的SqlSession對象final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get();if (sqlSession != null) {// 第二種模式try {return method.invoke(sqlSession, args);} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}} else {// 第一種模式 創(chuàng)建新的SqlSessionfinal SqlSession autoSqlSession = openSession();try {final Object result = method.invoke(autoSqlSession, args);autoSqlSession.commit();return result;} catch (Throwable t) {autoSqlSession.rollback();throw ExceptionUtil.unwrapThrowable(t);} finally {autoSqlSession.close();}}} }?
總結(jié)
以上是生活随笔為你收集整理的mybatis源码阅读(一):SqlSession和SqlSessionFactory的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 瑞典研究人员提出汽车废电池回收新方案,可
- 下一篇: 我国学者构建液态金属磁性微型软体机器人,