最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Mybatis StatementHandler的使用小結(jié)

 更新時(shí)間:2026年03月30日 08:33:30   作者:靈魂獵手  
本文主要介紹了Mybatis StatementHandler的使用小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、從Executor說起

之前著重講解了Executor實(shí)現(xiàn)的一二級(jí)緩存功能,現(xiàn)在我們回到Executor的核心的執(zhí)行SQL的能力,以SimpleExecutor為例:

@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
  Statement stmt = null;
  try {
    Configuration configuration = ms.getConfiguration();
    // 創(chuàng)建 StatementHandler
    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
    // 準(zhǔn)備 Statement
    stmt = prepareStatement(handler, ms.getStatementLog());
    // 執(zhí)行查詢
    return handler.query(stmt, resultHandler);
  } finally {
    closeStatement(stmt);
  }
}

private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
  Statement stmt;
  Connection connection = getConnection(statementLog);
  // 調(diào)用 StatementHandler 的 prepare 方法創(chuàng)建 Statement
  stmt = handler.prepare(connection, transaction.getTimeout());
  // 調(diào)用 StatementHandler 的 parameterize 方法設(shè)置參數(shù)
  handler.parameterize(stmt);
  return stmt;
}

通過源碼可以看到,SQL執(zhí)行的代碼非常簡(jiǎn)單:

  1. 從configuration中,構(gòu)造StatementHandler。
  2. 調(diào)用StatementHandler,構(gòu)造JDBC的Statement。
  3. 調(diào)用StatementHandler的parameterize,設(shè)置參數(shù)。
  4. 調(diào)用StatementHandler的query方法(更新則調(diào)用update方法)。

簡(jiǎn)而言之,Executor通過StatementHandler,實(shí)現(xiàn)SQL執(zhí)行的功能。

二、StatementHandler接口方法

StatementHandler 接口定義了與數(shù)據(jù)庫交互的核心方法,覆蓋了從SQL準(zhǔn)備、參數(shù)設(shè)置到執(zhí)行的完整流程:

方法簽名作用描述
Statement prepare(Connection connection, Integer transactionTimeout)創(chuàng)建并初始化數(shù)據(jù)庫執(zhí)行語句(Statement/PreparedStatement),完成 SQL 預(yù)編譯
void parameterize(Statement statement)為預(yù)編譯 SQL 設(shè)置參數(shù)(將 Java 對(duì)象映射到 SQL 占位符?)
int batch(Statement statement)執(zhí)行批量 SQL 操作(如批量插入 / 更新),返回批處理數(shù)量
int update(Statement statement)執(zhí)行增刪改操作,返回影響的行數(shù)
List<Object> query(Statement statement, ResultHandler resultHandler)執(zhí)行查詢操作,通過 ResultHandler 將結(jié)果集映射為 Java 對(duì)象
<T> Cursor<T> queryCursor(Statement statement)執(zhí)行查詢并返回 Cursor 對(duì)象,用于流式處理大數(shù)據(jù)集
BoundSql getBoundSql()獲取封裝 SQL 語句和參數(shù)信息的 BoundSql 對(duì)象
ParameterHandler getParameterHandler()獲取參數(shù)處理器 ParameterHandler(用于參數(shù)設(shè)置)

三、代碼實(shí)現(xiàn)

3.1 概述

classDiagram
    direction TB
    class StatementHandler {
        <<interface>>
        +prepare(Connection, Integer) Statement
        +parameterize(Statement) void
        +batch(Statement) int
        +update(Statement) int
        +query(Statement, ResultHandler) List~Object~
        +queryCursor(Statement) Cursor~T~
        +getBoundSql() BoundSql
        +getParameterHandler() ParameterHandler
    }
    class BaseStatementHandler {
        <<abstract>>
        -configuration: Configuration
        -executor: Executor
        -mappedStatement: MappedStatement
        -parameterHandler: ParameterHandler
        -resultSetHandler: ResultSetHandler
        -boundSql: BoundSql
        +prepare(Connection, Integer) Statement
        +getBoundSql() BoundSql
        +getParameterHandler() ParameterHandler
    }
    class SimpleStatementHandler
    class PreparedStatementHandler
    class CallableStatementHandler
    class RoutingStatementHandler
    StatementHandler <|-- BaseStatementHandler
    BaseStatementHandler <|-- SimpleStatementHandler
    BaseStatementHandler <|-- PreparedStatementHandler
    BaseStatementHandler <|-- CallableStatementHandler
    StatementHandler <|-- RoutingStatementHandler
    RoutingStatementHandler *-- StatementHandler : delegates

StatementHandler有四個(gè)核心實(shí)現(xiàn)類,關(guān)系與作用如下:

  • BaseStatementHandler:模板模式的抽象基類,定義了一些基礎(chǔ)屬性&方法,核心實(shí)現(xiàn)了prepare,定義了抽象的instantiateStatement方法,留給子類是實(shí)現(xiàn)。有三個(gè)子類:
    • SimpleStatementHandler 對(duì)應(yīng) JDBC 的 Statement,處理無參數(shù)靜態(tài) SQL;
    • PreparedStatementHandler 對(duì)應(yīng) PreparedStatement,處理帶參數(shù)預(yù)編譯 SQL(默認(rèn)使用);
    • CallableStatementHandler 對(duì)應(yīng) CallableStatement,用于調(diào)用存儲(chǔ)過程。
  • RoutingStatementHandler 是路由處理器,自身不處理邏輯,而是根據(jù)MappedStatement的statementType動(dòng)態(tài)選擇上述三個(gè)實(shí)現(xiàn)類之一進(jìn)行委派,簡(jiǎn)化了客戶端調(diào)用。

3.2RoutingStatementHandler- Handler路由器

RoutingStatementHandler是典型的代理模式,在構(gòu)造函數(shù)中,根據(jù)MappedStatement的statementType選擇具體的StatementHandler:

private final StatementHandler delegate;
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
  // 根據(jù)statementType選擇具體的StatementHandler
  switch (ms.getStatementType()) {
    case STATEMENT:
      delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
      break;
    case PREPARED:
      delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
      break;
    case CALLABLE:
      delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
      break;
    default:
      throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
  }
}
@Override  
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {  
    return delegate.prepare(connection, transactionTimeout);  
}
// 其他代理方法忽略。。。

PS:MappedStatement的statementType默認(rèn)是PREPARED,可以在xml或者注解中配置statementType屬性。

3.3 BaseStatementHandler 模板模式的基類

BaseStatementHandler源碼中,比較重要的是這個(gè)prepare方法,實(shí)現(xiàn)了通用流程,具體的JDBC的Statement創(chuàng)建邏輯,由子類通過instantiateStatement方法實(shí)現(xiàn)。

@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
  ErrorContext.instance().sql(boundSql.getSql());
  Statement statement = null;
  try {
    // 由子類實(shí)現(xiàn)具體的Statement創(chuàng)建
    statement = instantiateStatement(connection);
    // 設(shè)置超時(shí)時(shí)間
    setStatementTimeout(statement, transactionTimeout);
    // 設(shè)置fetchSize
    setFetchSize(statement);
    return statement;
  } catch (SQLException e) {
    closeStatement(statement);
    throw e;
  }
}
// 需要子類實(shí)現(xiàn)
protected abstract Statement instantiateStatement(Connection connection) throws SQLException;

3.4 instantiateStatement方法

各個(gè)子類的instantiateStatement發(fā)放,就是使用不同的姿勢(shì)調(diào)用JDBC的API:

  1. SimpleStatementHandler 對(duì)應(yīng) JDBC 的 Statement
@Override  
protected Statement instantiateStatement(Connection connection) throws SQLException {  
    if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {  
        return connection.createStatement();  
    } else {  
        return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);  
    }  
}
  1. PreparedStatementHandler 對(duì)應(yīng) PreparedStatement
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
  String sql = boundSql.getSql();
  // 處理自增主鍵
  if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
    String[] keyColumnNames = mappedStatement.getKeyColumns();
    if (keyColumnNames == null) {
      return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
    } else {
      return connection.prepareStatement(sql, keyColumnNames);
    }
  } else if (mappedStatement.getResultSetType() != null) {
    // 處理結(jié)果集類型
    return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
  } else {
    // 普通PreparedStatement創(chuàng)建
    return connection.prepareStatement(sql);
  }
}
  1. CallableStatementHandler 對(duì)應(yīng) CallableStatement:
@Override  
protected Statement instantiateStatement(Connection connection) throws SQLException {  
    String sql = boundSql.getSql();  
    if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {  
        return connection.prepareCall(sql);  
    } else {  
        return connection.prepareCall(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);  
    }  
}

3.5 處理參數(shù)&結(jié)果

StatementHandler的參數(shù)處理&結(jié)果處理,分別委托給ParameterHandler&ResultSetHandler(注意不是ResultHandler)??梢哉f,Mybatis把單一職責(zé)進(jìn)行到底。

PreparedStatementHandler參數(shù)&結(jié)果處理:

@Override
public void parameterize(Statement statement) throws SQLException {
  // 委托ParameterHandler設(shè)置參數(shù)
  parameterHandler.setParameters((PreparedStatement) statement);
}
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
  PreparedStatement ps = (PreparedStatement) statement;
  ps.execute();
  // 委托ResultSetHandler處理結(jié)果集
  return resultSetHandler.handleResultSets(ps);
}

四、小結(jié)

StatementHandler是MyBatis中負(fù)責(zé)與數(shù)據(jù)庫交互的核心組件,封裝了JDBC的Statement相關(guān)操作,提供了統(tǒng)一的接口:

  • SQL 語句的準(zhǔn)備(預(yù)編譯)
  • 參數(shù)綁定
  • SQL執(zhí)行(查詢、更新、批量操作等),這里也包含了結(jié)果處理。

StatementHandler實(shí)現(xiàn)過程中,使用了模板、策略以及代理模式。并且很好的體現(xiàn)了單一職責(zé)原則,參數(shù)處理&結(jié)果處理,分別委托給ParameterHandler&ResultSetHandler(注意不是ResultHandler),這兩個(gè)Handler我們后續(xù)再講。

到此這篇關(guān)于Mybatis StatementHandler的使用小結(jié)的文章就介紹到這了,更多相關(guān)Mybatis StatementHandler內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MyBatis 使用權(quán)威指南

    MyBatis 使用權(quán)威指南

    MyBatis 是支持定制化 SQL、存儲(chǔ)過程以及高級(jí)映射的優(yōu)秀的持久層框架。MyBatis 避免了幾乎所有的 JDBC 代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集,本文給大家介紹MyBatis 使用指南,一起看看吧
    2017-03-03
  • Minio的使用教程

    Minio的使用教程

    Minio是一個(gè)開源的對(duì)象存儲(chǔ)服務(wù),兼容Amazon?S3接口,適合存儲(chǔ)大容量非結(jié)構(gòu)化數(shù)據(jù),它部署簡(jiǎn)單,支持海量存儲(chǔ)和分布式部署,通過配置文件和systemd服務(wù),可以輕松設(shè)置和管理Minio服務(wù),本文介紹Minio的使用教程,感興趣的朋友一起看看吧
    2025-02-02
  • Spring @Primary和@Qualifier注解原理解析

    Spring @Primary和@Qualifier注解原理解析

    這篇文章主要介紹了Spring @Primary和@Qualifier注解原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 使用chatgpt實(shí)現(xiàn)微信聊天小程序的代碼示例

    使用chatgpt實(shí)現(xiàn)微信聊天小程序的代碼示例

    這篇文章主要介紹了使用chatgpt實(shí)現(xiàn)微信聊天小程序(秒回復(fù)),文中有詳細(xì)的代碼示例,對(duì)大家了解chatgpt聊天有一定的幫助,感興趣的同學(xué)可以參考閱讀
    2023-05-05
  • 如何解決IDEA中JSP頁面部分出現(xiàn)綠色背景色問題

    如何解決IDEA中JSP頁面部分出現(xiàn)綠色背景色問題

    這篇文章主要介紹了如何解決IDEA中JSP頁面部分出現(xiàn)綠色背景色問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • maven關(guān)于pom文件中的relativePath標(biāo)簽使用

    maven關(guān)于pom文件中的relativePath標(biāo)簽使用

    在Maven項(xiàng)目中,子工程通過<relativePath>標(biāo)簽指定父工程的pom.xml位置,以確保正確繼承父工程的配置,這個(gè)標(biāo)簽可以配置為默認(rèn)值、空值或自定義值,默認(rèn)情況下,Maven會(huì)向上一級(jí)目錄尋找父pom;若配置為空值
    2024-09-09
  • MyBatis執(zhí)行SQL的兩種方式小結(jié)

    MyBatis執(zhí)行SQL的兩種方式小結(jié)

    本文主要介紹了MyBatis執(zhí)行SQL的兩種方式小結(jié),主要包括SqlSession 發(fā)送SQL和SqlSession獲取Mapper接口,通過Mapper接口發(fā)送SQL,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • 使用Netty快速實(shí)現(xiàn)一個(gè)群聊功能的示例詳解

    使用Netty快速實(shí)現(xiàn)一個(gè)群聊功能的示例詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用?Netty?框架開發(fā)一個(gè)?WebSocket?服務(wù)端,從而實(shí)現(xiàn)一個(gè)簡(jiǎn)單的在線聊天功能,感興趣的小伙伴可以了解下
    2023-11-11
  • 快速解決idea打開某個(gè)項(xiàng)目卡住的問題

    快速解決idea打開某個(gè)項(xiàng)目卡住的問題

    這篇文章主要介紹了解決idea打開某個(gè)項(xiàng)目卡住的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Springboot項(xiàng)目集成SkyWalking鏈路追蹤系統(tǒng)實(shí)戰(zhàn)指南

    Springboot項(xiàng)目集成SkyWalking鏈路追蹤系統(tǒng)實(shí)戰(zhàn)指南

    本文詳解SpringBoot集成SkyWalking鏈路追蹤的步驟,涵蓋Agent部署、配置參數(shù)設(shè)置(含服務(wù)名、后端地址、認(rèn)證token)、多啟動(dòng)方式及日志對(duì)接方法,但未充分說明環(huán)境變量配置細(xì)節(jié)和gRPC認(rèn)證參數(shù)的使用場(chǎng)景,需要的朋友跟隨小編一起看看吧
    2025-08-08

最新評(píng)論

锦州市| 武威市| 武冈市| 凤翔县| 台中市| 河源市| 中超| 福清市| 金坛市| 山丹县| 小金县| 东乌珠穆沁旗| 项城市| 沽源县| 冕宁县| 二连浩特市| 莱阳市| 泸溪县| 天柱县| 措美县| 南澳县| 原阳县| 策勒县| 海口市| 桐柏县| 永安市| 永定县| 赞皇县| 南华县| 岳西县| 府谷县| 岳阳市| 连山| 花垣县| 杭州市| 黄骅市| 新安县| 易门县| 梨树县| 繁昌县| 临夏市|