1. 程式人生 > 程式設計 >詳解mybatis @SelectProvider 註解

詳解mybatis @SelectProvider 註解

01、前言

為什麼會寫這篇文章,因為在看到 MapperAnnotationBuilder 構造方法初始化時,發現了四個從未見過的註解

public MapperAnnotationBuilder(Configuration configuration,Class<?> type) {
  ...
  sqlAnnotationTypes.add(Select.class);
  sqlAnnotationTypes.add(Insert.class);
  sqlAnnotationTypes.add(Update.class);
  sqlAnnotationTypes.add(Delete.class);
  // 這四個註解眼生的很
  sqlProviderAnnotationTypes.add(SelectProvider.class);
  sqlProviderAnnotationTypes.add(InsertProvider.class);
  sqlProviderAnnotationTypes.add(UpdateProvider.class);
  sqlProviderAnnotationTypes.add(DeleteProvider.class);
}

@SelectProvider、@InsertProvider、@UpdateProvider、@DeleteProvider

分別是 mybatis 定義的 另類增刪改查註解

02、介紹篇

四個註解中分別都有兩個屬性,這裡以 @SelectProvider舉例

可以看到,兩個屬性並沒有預設值,證明定義註解的話,這兩個屬性必須組合使用

沒有看到這一塊的具體解析原始碼,不過也能猜出來,根據反射呼叫方法獲取的返回值

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface InsertProvider {
  // 用於指定獲取 sql 語句的指定類
  Class<?> type();
  // 指定類中要執行獲取 sql 語句的方法
  String method();
}

03、實戰篇

如何根據註解定義 sql 語句呢,首先定義 mapper 介面

public interface AutoConstructorMapper {
  @SelectProvider(type = SubjectSqlProvider.class,method = "getSubjectTestProvider")
  PrimitiveSubject getSubjectTestProvider(@Param("id") int id);
}

@Param() 為必須,在解析時會將引數定義為 map,進行呼叫指定 method

建立 type 對應的存放 sql 語句的類,以及定義返回 sql 語句的方法

有三點需要注意:

  • 方法入參必須為 Map
  • 方法的許可權修飾符 必須是 public
  • 方法返回的必須是拼接好的 sql 字串
public class SubjectSqlProvider {
  public String getSubjectTestProvider(Map<String,Object> params) {
    return new SQL()
        .SELECT("*")
        .FROM("subject")
        .WHERE("id = " + params.get("id"))
        .toString();
  }
}

SQL 類是 mybatis 提供開發者在程式碼中靈活編寫 sql 語句的工具類

04、思考篇

思考一下,@SelectProvider 註解,與 @Select 註解解析流程有什麼不同?

@Select@SelectProvider 只是在定義註解的方式上有所不同,一個是直接定義 sql,一個是在外部定義好 sql 直接引用,沒有質的區別

在 mybatis 初始化定義 MappedStatement 時,使用了兩種不同的邏輯進行組裝 SqlSource

Class<? extends Annotation> sqlAnnotationType = getSqlAnnotationType(method);
Class<? extends Annotation> sqlProviderAnnotationType = getSqlProviderAnnotationType(method);
if (sqlAnnotationType != null) {
  if (sqlProviderAnnotationType != null) {
    throw new BindingException("You cannot supply both a static SQL and SqlProvider to method named " + method.getName());
  }
  Annotation sqlAnnotation = method.getAnnotation(sqlAnnotationType);
  final String[] strings = (String[]) sqlAnnotation.getClass().getMethod("value").invoke(sqlAnnotation);
  return buildSqlSourceFromStrings(strings,parameterType,languageDriver);
} else if (sqlProviderAnnotationType != null) {
  Annotation sqlProviderAnnotation = method.getAnnotation(sqlProviderAnnotationType);
  return new ProviderSqlSource(assistant.getConfiguration(),sqlProviderAnnotation,type,method);
}

05、使用篇

這裡介紹下 mybatis 具體編寫 SQL 的三種形式,以及介紹不同的方式對應的使用場景

5.1 @Select

這種方式能夠定義簡單的 sql,不涉及複雜查詢和多引數的場景,類似下述方式

@Select 定義 sql 的方式是最簡單的,省去了定義 xml檔案的繁瑣,也少了定義編寫 @SelectProvider 對應類和方法的步驟

SELECT * FROM subject WHERE id = #{id}

5.2 @SelectProvider

這種方式編寫sql適合編寫中等長度,簡單的查詢搭配 join、group、order…

SQL 工具類提供了這種簡單的 API 語法,還是比較方便的

如果不想使用 SQL 工具類,自己編寫 sql 字串也是可以的

詳解mybatis @SelectProvider 註解

5.3 .xml 檔案

這種方式就不多說了,功能全部具備,比如計算函式、動態SQL、各種關鍵字都支援

這幾種方式都能夠實現我們的 sql 編寫需求,只不過針對不同的場景,合理的使用即可

06、總結篇

看 mybatis 原始碼,對變數、方法的命名加深了感觸,一個好的變數或者方法命名在程式碼中是多麼有必要

getSqlSourceFromAnnotations 是不是要比 getSqlSource 要好理解很多,看了之後就能讓閱讀者知道這個方法要做什麼功能

到此這篇關於詳解mybatis @SelectProvider 註解的文章就介紹到這了,更多相關mybatis @SelectProvider 註解內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!