日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

mybatis源码阅读(一):SqlSession和SqlSessionFactory

發布時間:2023/12/3 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mybatis源码阅读(一):SqlSession和SqlSessionFactory 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自??mybatis源碼閱讀(一):SqlSession和SqlSessionFactory?

一、接口定義

????聽名字就知道這里使用了工廠方法模式,SqlSessionFactory負責創建SqlSession對象。其中開發人員最常用的就是DefaultSqlSession

(1)SqlSession接口定義

public interface SqlSession extends Closeable {// 泛型方法,參數表示使用的查詢SQL語句,返回值為查詢的結果對象<T> T selectOne(String statement);// 第二個參數表示需要用戶傳入的實參,也就是SQL語句綁定的實參<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);/**** selectMap 方法的原理和參數都與selectList方法類型,但結果集會被映射成Map對象返回* 其中mapKey參數指定了結果集哪一列作為map的key,其他參數同上*/<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);// 查詢的結果對象將由此處指定的handler對象處理,其余參數同上void select(String statement, Object parameter, ResultHandler handler);void select(String statement, ResultHandler handler);void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);// 執行insert語句int insert(String statement);int insert(String statement, Object parameter);// 執行update語句int update(String statement);int update(String statement, Object parameter);// 執行deleteint delete(String statement);int delete(String statement, Object parameter);// 提交事務void commit();void commit(boolean force);// 事務回滾void rollback();void rollback(boolean force);// 將請求刷新到數據庫List<BatchResult> flushStatements();// 關閉當前session@Overridevoid close();// 清空session 緩存void clearCache();// 獲取Configuration 對象Configuration getConfiguration();// 獲取type 對象的Mapper對象<T> T getMapper(Class<T> type);// 獲取該Sqlsession 對象的數據庫連接Connection getConnection(); }

SqlSession數據庫的C、R、U、D及事務處理接口,你懂的。

(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(); }

這個大家也都懂的

SqlSession實現類:DefaultSqlSession和SqlSessionManager

SqlSessionFactory實現類: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();} }

這里主要看這兩個方法,因為delete和insert最終執行掉用的都是update方法,查詢就更不用說了。從代碼上看都是從configuration對象中獲取MappedStatement 對象 然后把事情交給小弟Executor去執行,這里用了很典型的策略設計模式,這個關于Executor 后面介紹。

(4)DefaultSqlSessionFactory

/*** 通過數據源獲取數據庫連接,并創建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();} }/*** 用戶提供數據庫連接對象,使用該數據庫連接對象創建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主要提供了兩種創建DefaultSqlSession對象的方式,一種是通過數據源獲取數據庫連接,并創建Executor以及DefaultSqlSession對象,另一種是用戶提供數據庫連接對象,使用該數據庫連接對象創建Executor和DefaultSqlSession對象。

(5)SqlSessionManager

SqlSessionManager同時實現SqlSession接口和SqlSessionFactory接口,也就是同時提供了創建SqlSession對象以及SqlSession對象操作數據庫的功能。SqlSessionManager與DefaultSqlSessionFactory的主要不同點是SqlSessionManager提供了兩種模式,一種是和DefaultSqlSessionFactory的行為相同,同一線程每次訪問數據庫就都會創建新的DefaultSqlSession,第二種是通過ThreadLocal變量記錄當前線程的SqlSession對象,避免同一線程多次創建SqlSession對象。至于使用動態代理的目的,是為了通過攔截器InvocationHandler,增強目標target的方法調用。

private final SqlSessionFactory sqlSessionFactory; // SqlSession的代理對象 會使用JDK的動態代理方式實現 private final SqlSession sqlSessionProxy;/*** ThreadLocal 變量,記錄一個與當前線程綁定的SqlSession對象* localSqlSession 中記錄的SqlSession對象的代理對象,在SqlSessionManager初始化的時候*/ private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<SqlSession>(); /*** SqlSessionManager 的私有構造方法*/ private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;// 使用動態代理生成SqlSession的代理對象this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(),new Class[]{SqlSession.class},new SqlSessionInterceptor()); }/*** 通過newInstance方法創建SqlSessionManager對象* @param reader* @return*/public static SqlSessionManager newInstance(Reader reader) {return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, null));} // 內部類 private class SqlSessionInterceptor implements InvocationHandler {public SqlSessionInterceptor() {// Prevent Synthetic Access}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 獲取當前線程綁定的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 {// 第一種模式 創建新的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();}}} }

?

總結

以上是生活随笔為你收集整理的mybatis源码阅读(一):SqlSession和SqlSessionFactory的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。