詳解mybatis @SelectProvider 注解
為什么會(huì)寫這篇文章, 因?yàn)樵诳吹?MapperAnnotationBuilder 構(gòu)造方法初始化時(shí), 發(fā)現(xiàn)了四個(gè)從未見(jiàn)過(guò)的注解
public MapperAnnotationBuilder(Configuration configuration, Class<?> type) { ... sqlAnnotationTypes.add(Select.class); sqlAnnotationTypes.add(Insert.class); sqlAnnotationTypes.add(Update.class); sqlAnnotationTypes.add(Delete.class); // 這四個(gè)注解眼生的很 sqlProviderAnnotationTypes.add(SelectProvider.class); sqlProviderAnnotationTypes.add(InsertProvider.class); sqlProviderAnnotationTypes.add(UpdateProvider.class); sqlProviderAnnotationTypes.add(DeleteProvider.class);}
@SelectProvider、@InsertProvider、@UpdateProvider、@DeleteProvider
分別是 mybatis 定義的 另類增刪改查注解
02、介紹篇四個(gè)注解中分別都有兩個(gè)屬性, 這里以 @SelectProvider舉例
可以看到, 兩個(gè)屬性并沒(méi)有默認(rèn)值, 證明定義注解的話, 這兩個(gè)屬性必須組合使用
沒(méi)有看到這一塊的具體解析源碼, 不過(guò)也能猜出來(lái), 根據(jù)反射調(diào)用方法獲取的返回值
@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface InsertProvider { // 用于指定獲取 sql 語(yǔ)句的指定類 Class<?> type(); // 指定類中要執(zhí)行獲取 sql 語(yǔ)句的方法 String method();}03、實(shí)戰(zhàn)篇
如何根據(jù)注解定義 sql 語(yǔ)句呢, 首先定義 mapper 接口
public interface AutoConstructorMapper { @SelectProvider(type = SubjectSqlProvider.class, method = 'getSubjectTestProvider') PrimitiveSubject getSubjectTestProvider(@Param('id') int id);}
@Param() 為必須, 在解析時(shí)會(huì)將參數(shù)定義為 map, 進(jìn)行調(diào)用指定 method
創(chuàng)建 type 對(duì)應(yīng)的存放 sql 語(yǔ)句的類, 以及定義返回 sql 語(yǔ)句的方法
有三點(diǎn)需要注意:
方法入?yún)⒈仨殲?Map 方法的權(quán)限修飾符 必須是 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 提供開發(fā)者在代碼中靈活編寫 sql 語(yǔ)句的工具類
04、思考篇思考一下, @SelectProvider 注解, 與 @Select 注解解析流程有什么不同?
@Select 與 @SelectProvider 只是在定義注解的方式上有所不同, 一個(gè)是直接定義 sql, 一個(gè)是在外部定義好 sql 直接引用, 沒(méi)有質(zhì)的區(qū)別
在 mybatis 初始化定義 MappedStatement 時(shí), 使用了兩種不同的邏輯進(jìn)行組裝 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 的三種形式, 以及介紹不同的方式對(duì)應(yīng)的使用場(chǎng)景
5.1 @Select這種方式能夠定義簡(jiǎn)單的 sql, 不涉及復(fù)雜查詢和多參數(shù)的場(chǎng)景, 類似下述方式
@Select 定義 sql 的方式是最簡(jiǎn)單的, 省去了定義 xml文件的繁瑣, 也少了定義編寫 @SelectProvider 對(duì)應(yīng)類和方法的步驟
SELECT * FROM subject WHERE id = #{id}5.2 @SelectProvider
這種方式編寫sql適合編寫中等長(zhǎng)度, 簡(jiǎn)單的查詢搭配 join、group、order…
SQL 工具類提供了這種簡(jiǎn)單的 API 語(yǔ)法, 還是比較方便的
如果不想使用 SQL 工具類, 自己編寫 sql 字符串也是可以的

這種方式就不多說(shuō)了, 功能全部具備, 比如計(jì)算函數(shù)、動(dòng)態(tài)SQL、各種關(guān)鍵字都支持
這幾種方式都能夠?qū)崿F(xiàn)我們的 sql 編寫需求, 只不過(guò)針對(duì)不同的場(chǎng)景, 合理的使用即可
06、總結(jié)篇看 mybatis 源碼, 對(duì)變量、方法的命名加深了感觸, 一個(gè)好的變量或者方法命名在代碼中是多么有必要
getSqlSourceFromAnnotations 是不是要比 getSqlSource 要好理解很多, 看了之后就能讓閱讀者知道這個(gè)方法要做什么功能
到此這篇關(guān)于詳解mybatis @SelectProvider 注解的文章就介紹到這了,更多相關(guān)mybatis @SelectProvider 注解內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. 學(xué)好Oracle的六條總結(jié)2. Mysql入門系列:在MYSQL結(jié)果集上執(zhí)行計(jì)算3. mysql like語(yǔ)句問(wèn)題4. mysql啟動(dòng)時(shí)報(bào)錯(cuò) ERROR! Manager of pid-file quit without5. 快速刪除ORACLE重復(fù)記錄6. 傳甲骨文將增加對(duì)MySQL投資與微軟競(jìng)爭(zhēng)7. mysql 視圖操作和存儲(chǔ)過(guò)程8. MySql遠(yuǎn)程連接的實(shí)現(xiàn)方法9. 巧用SQL語(yǔ)言在ACCESS數(shù)據(jù)庫(kù)中批量替換內(nèi)容

網(wǎng)公網(wǎng)安備