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

MyBatis中動(dòng)態(tài)SQL語(yǔ)句@Provider的用法

 更新時(shí)間:2023年06月22日 09:54:26   作者:大飯盒  
本文主要介紹了MyBatis中動(dòng)態(tài)SQL語(yǔ)句@Provider的用法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

Mybatis里的動(dòng)態(tài)SQL,估計(jì)用到的同學(xué)不是很多,畢竟在xml文件中定義sql語(yǔ)句的方式,已經(jīng)可以滿足絕大部分的開發(fā)需求,方便又簡(jiǎn)單。沒(méi)有痛點(diǎn),也就少了動(dòng)力。這一章就來(lái)聊聊這塊,對(duì)于有代碼潔癖的人來(lái)說(shuō),還是很賞心悅目的。

四個(gè)注解

@Provider系列的注解有四個(gè):

  • @SelectProvider,被定義用來(lái)提供查詢方法的SQL;
  • @UpdateProvider,被定義用來(lái)提供更新方法的SQL;
  • @DeleteProvider,被定義用來(lái)提供刪除方法的SQL;
  • @InsertProvider,被定義用來(lái)提供保存方法的SQL;

官方例子

public interface UserMapper {
  // 保存用戶數(shù)據(jù)
  @InsertProvider(type = SqlProvider.class, method = "insert")
  void insert(User user);
  public static class SqlProvider {
    // 對(duì)應(yīng)@InsertProvider注解里的method,返回對(duì)應(yīng)sql
    public static String insert() {
      return "INSERT INTO users (id, name) VALUES(#{id}, #{name})";
    }
  }
}

序列圖

此章節(jié)主要源碼都在ProviderSqlSource里。

源碼

這里介紹的源碼不多,主要是兩個(gè)部分

sql拼接;

  • 反射執(zhí)行provider方法;

sql拼接

sql拼接,主要依賴AbstractSQL里的靜態(tài)方法,下面講一下update語(yǔ)句。

  List<String> sets = new ArrayList<>();
  List<String> tables = new ArrayList<>();
  List<String> where = new ArrayList<>();
  public T UPDATE(String table) {
    // 指定類型為update
    sql().statementType = SQLStatement.StatementType.UPDATE;
    // 設(shè)定表名,tables集合添加元素
    sql().tables.add(table);
    // 返回當(dāng)前sqlBuilder對(duì)象
    return getSelf();
  }
    private String updateSQL(SafeAppendable builder) {
       // 拼接 UPDATE [table_name]
      sqlClause(builder, "UPDATE", tables, "", "", "");
      joins(builder);
      // 拼接sets集合
      sqlClause(builder, "SET", sets, "", "", ", ");
      // 拼接where條件集合
      sqlClause(builder, "WHERE", where, "(", ")", " AND ");
      // 拼接限定條件
      limitingRowsStrategy.appendClause(builder, null, limit);
      return builder.toString();
    }

注意:sql拼接是按照一定順序的,tables -> sets -> where,就算是我們?cè)诖a里,刻意打亂順序,也沒(méi)有影響,比如:

 WHERE("md5 = #{md5}");
 SET("update_time = NOW()");
 UPDATE(tableName);

其實(shí)是可以的,畢竟Provider本質(zhì)上,就是提供了待執(zhí)行的sql預(yù)處理語(yǔ)句??垂俜降睦?,其實(shí)就沒(méi)有使用拼接,在后面的例子里,如果不進(jìn)行參數(shù)判空,可以寫成這樣:

public String updateStatus() {
    return "UPDATE tb_image SET update_time = NOW(), status = ? WHERE (md5 = ?) AND (status = ?)";
}

反射執(zhí)行provider方法

  private String invokeProviderMethod(Object... args) throws Exception {
    Object targetObject = null;
    if (!Modifier.isStatic(providerMethod.getModifiers())) {
      // 如果是非靜態(tài)方法,則需要一個(gè)類實(shí)例
      targetObject = providerType.getDeclaredConstructor().newInstance();
    }
    // 反射執(zhí)行@Provider里指定的方法
    CharSequence sql = (CharSequence) providerMethod.invoke(targetObject, args);
    // 返回sql語(yǔ)句
    return sql != null ? sql.toString() : null;
  }

這里返回的sql語(yǔ)句,是基于JDBC預(yù)處理語(yǔ)法的字符串,例如UPDATE tb_image SET update_time = NOW(), status = ? WHERE (md5 = ?) AND (status = ?)

參數(shù)是怎么處理的

CharSequence sql = (CharSequence) providerMethod.invoke(targetObject, args);這一行代碼里,指定了方法參數(shù)【args】,首先說(shuō)明,provider方法里的參數(shù),都來(lái)自于Mapper里的方法參數(shù)值,從params里獲取對(duì)應(yīng)參數(shù)名稱的值,寫入到args;

  private Object[] extractProviderMethodArguments(Map<String, Object> params, String[] argumentNames) {
    Object[] args = new Object[argumentNames.length];
    for (int i = 0; i < args.length; i++) {
      if (providerContextIndex != null && providerContextIndex == i) {
        args[i] = providerContext;
      } else {
        // 關(guān)鍵就是這一句,從params里獲取對(duì)應(yīng)參數(shù)名稱的值,寫入到args;
        args[i] = params.get(argumentNames[i]);
      }
    }
    return args;
  }

方法參數(shù)介紹

  • params:Mapper里對(duì)應(yīng)方法的所有參數(shù);
  • argumentNames:Provider里方法的參數(shù)名稱;

這是下面例子里的參數(shù)處理結(jié)果

我的例子

provider

注意provider里方法的參數(shù),可以和mapper參數(shù)一致,也可以缺失幾個(gè)。引用mapper的參數(shù),主要是為了進(jìn)行邏輯分支判定。

public class ImageDynamicProvider {
    /**
     * 圖片更新
     *
     * @return sql
     */
    public String updateStatus(Integer newStatus, Integer oldStatus) {
        Table table = ImageInfo.class.getAnnotation(Table.class);
        String tableName = table.name();
        return new SQL() {
            {
                UPDATE(tableName);
                SET("update_time = NOW()");
                // 判定是否需要更新?tīng)顟B(tài)
                if (newStatus != null) {
                    SET("status = #{newStatus}");
                }
                WHERE("md5 = #{md5}");
                // 判定是否需要此條件
                if (oldStatus != null) {
                    AND().WHERE("status = #{oldStatus}");
                }
            }
        }.toString();
    }
}

引用Provider

在Mapper對(duì)應(yīng)的方法上面,根據(jù)具體類型,選擇注解。此處是更新語(yǔ)句,所以使用@UpdateProvider,參數(shù)提供了具體的類和方法,供后續(xù)執(zhí)行反射方法。

    /**
     * 更新?tīng)顟B(tài)
     *
     * @param md5 圖片摘要信息
     */
    @UpdateProvider(value = ImageDynamicProvider.class, method = "updateStatus")
    int updateStatusByProvider(@Param(value = "md5") String md5,
                               @Param(value = "oldStatus") int oldStatus,
                               @Param(value = "newStatus") int newStatus);

測(cè)試用例

    @Test
    public void provider() {
        imageInfoMapper.updateStatusByProvider( "6e705a7733ac5gbwopmp02", 50, 199);
    }

輸出

==>  Preparing: UPDATE tb_image SET update_time = NOW(), status = ? WHERE (md5 = ?) AND (status = ?)
==> Parameters: 199(Integer), 6e705a7733ac5gbwopmp02(String), 50(Integer)
<==    Updates: 1

小問(wèn)題

如果既有Provider,也有xml方法映射。就是說(shuō)我們定義了@Provider注解,又在xml中寫了mapper方法的映射sql語(yǔ)句,這種場(chǎng)景,Mybatis在啟動(dòng)時(shí)就會(huì)報(bào)錯(cuò)。

nested exception is java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.essay.dao.ImageInfoMapper.updateStatusProvider

到此這篇關(guān)于MyBatis中動(dòng)態(tài)SQL語(yǔ)句@Provider的用法的文章就介紹到這了,更多相關(guān)MyBatis 動(dòng)態(tài)SQL @Provider內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java面試題沖刺第九天--MyBatis

    Java面試題沖刺第九天--MyBatis

    這篇文章主要為大家分享了最有價(jià)值的三道MyBatis框架面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Spring實(shí)戰(zhàn)之搜索Bean類操作示例

    Spring實(shí)戰(zhàn)之搜索Bean類操作示例

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之搜索Bean類操作,結(jié)合實(shí)例形式分析了Spring搜索Bean類的相關(guān)配置、接口實(shí)現(xiàn)與操作技巧,需要的朋友可以參考下
    2019-12-12
  • Java實(shí)現(xiàn)三個(gè)線程進(jìn)行順序打印的兩種方案

    Java實(shí)現(xiàn)三個(gè)線程進(jìn)行順序打印的兩種方案

    三個(gè)線程按順序打印是一個(gè)經(jīng)典的并發(fā)編程面試題,通常要求線程 A 打印 1,線程 B 打印 2,線程 C 打印 3,然后循環(huán)往復(fù),所以本文給大家介紹了Java實(shí)現(xiàn)三個(gè)線程進(jìn)行順序打印的兩種方案的相關(guān)資料,需要的朋友可以參考下
    2026-01-01
  • Maven打包JavaWeb項(xiàng)目的兩種實(shí)現(xiàn)方式

    Maven打包JavaWeb項(xiàng)目的兩種實(shí)現(xiàn)方式

    介紹了兩種Maven打包Web項(xiàng)目的方式:通過(guò)Eclipse和通過(guò)命令行,Eclipse方式包括清理、打包、跳過(guò)測(cè)試、輸入?Goals?等步驟,命令行方式包括進(jìn)入項(xiàng)目目錄、執(zhí)行?clean?和?package?命令、跳過(guò)測(cè)試等步驟,注意事項(xiàng)包括確保有JDK環(huán)境、正確配置pom.xml文件和修改版本號(hào)
    2025-02-02
  • 解決使用this.getClass().getResource()獲取文件時(shí)遇到的坑

    解決使用this.getClass().getResource()獲取文件時(shí)遇到的坑

    這篇文章主要介紹了解決使用this.getClass().getResource()獲取文件時(shí)遇到的坑問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 淺析Java基于Socket的文件傳輸案例

    淺析Java基于Socket的文件傳輸案例

    這篇文章主要針對(duì)Java基于Socket的文件傳輸案例進(jìn)行詳細(xì)解析,具有一定的參考價(jià)值,感興趣的朋友可以參考一下
    2016-02-02
  • Java開發(fā)異步編程中常用的接口和類示例詳解

    Java開發(fā)異步編程中常用的接口和類示例詳解

    在現(xiàn)代Java中異步編程通常通過(guò)不同的機(jī)制和接口來(lái)實(shí)現(xiàn),這篇文章主要介紹了Java開發(fā)異步編程中常用的接口和類的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),+需要的朋友可以參考下
    2025-08-08
  • 使用Filter實(shí)現(xiàn)登錄權(quán)限驗(yàn)證

    使用Filter實(shí)現(xiàn)登錄權(quán)限驗(yàn)證

    這篇文章主要為大家詳細(xì)介紹了使用Filter實(shí)現(xiàn)登錄權(quán)限驗(yàn)證,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • Java創(chuàng)建多線程服務(wù)器流程

    Java創(chuàng)建多線程服務(wù)器流程

    這篇文章主要介紹了Java創(chuàng)建多線程服務(wù)器流程,以下實(shí)例演示了如何使用Socket類的accept()方法和ServerSocket類的MultiThreadServer(socketname)方法來(lái)實(shí)現(xiàn)多線程服務(wù)器程序
    2023-05-05
  • MyBatis核心概念?+?環(huán)境搭建?+?CRUD實(shí)戰(zhàn)詳解

    MyBatis核心概念?+?環(huán)境搭建?+?CRUD實(shí)戰(zhàn)詳解

    文章主要介紹了MyBatis的核心知識(shí),從JDBC痛點(diǎn)開始,闡述了MyBatis的優(yōu)勢(shì),包括連接池管理、SQL與Java代碼解耦、自動(dòng)結(jié)果集映射、參數(shù)自動(dòng)映射等,感興趣的朋友跟隨小編一起看看吧
    2026-05-05

最新評(píng)論

岳阳县| 德阳市| 合山市| 西盟| 固安县| 高尔夫| 台东市| 剑川县| 齐齐哈尔市| 九江县| 吴江市| 元谋县| 武城县| 洪雅县| 登封市| 广灵县| 大余县| 滨州市| 探索| 宁明县| 乐安县| 衡阳县| 孟村| 庆安县| 伊宁县| 邳州市| 和田县| 达拉特旗| 石河子市| 和林格尔县| 花莲县| 博乐市| 哈密市| 米林县| 乌审旗| 山西省| 湖口县| 太和县| 临沂市| 邵阳市| 灌南县|