mybatis-plus鏈式調(diào)用的實現(xiàn)示例
mybatis-plus相信大家都不陌生,尤其在需要快速開發(fā)的時候,使用mp進行開發(fā),確實能提高效率,在使用的過程中,一直都很好奇,mp是如何實現(xiàn)鏈式調(diào)用的
源碼解析
從最經(jīng)典的LambdaQueryWrapper入手,點開源碼會發(fā)現(xiàn),調(diào)用的函數(shù)返回了typedThis,確實是很經(jīng)典的鏈式的設(shè)計,所謂鏈式調(diào)用,就是通過設(shè)置方法的返回值,讓返回值變?yōu)閷ο笞陨?,從而實現(xiàn)連續(xù)的方法調(diào)用
public class LambdaQueryWrapper<T> extends AbstractLambdaWrapper<T, LambdaQueryWrapper<T>>
implements Query<LambdaQueryWrapper<T>, T, SFunction<T, ?>> {
// 省略構(gòu)造函數(shù)
/**
* SELECT 部分 SQL 設(shè)置
*
* @param columns 查詢字段
*/
@SafeVarargs
@Override
public final LambdaQueryWrapper<T> select(SFunction<T, ?>... columns) {
if (ArrayUtils.isNotEmpty(columns)) {
this.sqlSelect.setStringValue(columnsToString(false, columns));
}
return typedThis;
} @Override
public LambdaQueryWrapper<T> select(Class<T> entityClass, Predicate<TableFieldInfo> predicate) {
if (entityClass == null) {
entityClass = getEntityClass();
} else {
setEntityClass(entityClass);
}
Assert.notNull(entityClass, "entityClass can not be null");
this.sqlSelect.setStringValue(TableInfoHelper.getTableInfo(entityClass).chooseSelect(predicate));
return typedThis;
}
追蹤一下typedThis,會發(fā)現(xiàn)來到了AbstractWrapper中,看來這里就是真正實現(xiàn)鏈式調(diào)用的地方,看到這里原諒我孤陋寡聞,確實沒怎么用泛型,原來還能這么用的??。
public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T, R, Children>> extends Wrapper<T>
implements Compare<Children, R>, Nested<Children, Children>, Join<Children>, Func<Children, R> {
/**
* 占位符
*/
protected final Children typedThis = (Children) this;
// 省略其余全局變量
@Override
public T getEntity() {
return entity;
}
public Children setEntity(T entity) {
this.entity = entity;
return typedThis;
}
//普通query的R指定的String,lambda的R指定的SFunction,用來實現(xiàn)方法的引用
@Override
public Children eq(boolean condition, R column, Object val) {
return addCondition(condition, column, EQ, val);
}
T,R其實都是泛型占位符,T大家應該都見過很多了,但為什么還有一個R呢?查看一下AbstractWrapper的實現(xiàn)類,會發(fā)現(xiàn)正常的query指定的是string,而lambdaquery指定的是SFunction<T, ?>,看來是實現(xiàn)lambdaquery的方法引用,具體的實現(xiàn)可以查看一下Query
public class QueryWrapper<T> extends AbstractWrapper<T, String, QueryWrapper<T>>
implements Query<QueryWrapper<T>, T, String> {
public abstract class AbstractLambdaWrapper<T, Children extends AbstractLambdaWrapper<T, Children>>
extends AbstractWrapper<T, SFunction<T, ?>, Children> {
那Children也是同理,是一個自引用的占位符,根據(jù)不同的子類實現(xiàn),強轉(zhuǎn)成不同的子類示例
自定義實現(xiàn)
知道了原理,就可以模仿一下mp的實現(xiàn),先定義一個抽象類,業(yè)務沒那么復雜,就不需要定義太多泛型,同時定義一些方法和抽象方法
@Slf4j
public abstract class AbstractLambdaESignBuilder <Children extends AbstractLambdaESignBuilder<Children>>{
/**
* 占位符
*/
protected final Children typedThis = (Children) this;
public Children preview(ESignInitiateParam initiateParam){
CreateDocTemplate createDocTemplate = new CreateDocTemplate();
createDocTemplate.setDocTemplateId(eSignConfig.getDocTemplateId());
createDocTemplate.setFileName(eSignConfig.getFileName());
List<Component> components = buildDebt(initiateParam);
createDocTemplate.setComponents(components);
body = JSONObject.toJSONString(createDocTemplate);
return typedThis;
}
public Children sortAPIUrl(String apiUrl){
this.sortApiUrl = apiUrl;
return typedThis;
}
protected abstract ESignModel get(String msg, String responseMsg);
protected abstract Children config(ESignConfig eSignConfig);
}
子類繼承一下,重寫父類的方法
@Slf4j
@Service
public class LambdaESignBuilder extends AbstractLambdaESignBuilder<LambdaESignBuilder> {
@Override
public LambdaESignBuilder config(ESignConfig eSignConfig) {
super.eSignConfig = eSignConfig;
return super.typedThis;
}
}
這樣就實現(xiàn)了一個簡易的鏈式調(diào)用方法了

總結(jié)
總的來說,mp通過在父類定義一個自引用的泛型來實現(xiàn)鏈式調(diào)用,之后繼承該父類的子類,只要重寫父類定義的方法,既可實現(xiàn)鏈式調(diào)用,同時又定義了多個泛型類型,子類根據(jù)不同的業(yè)務需求,自定義方法的入?yún)⒑统鰠?。對于泛型的使用是一個很好的例子
到此這篇關(guān)于mybatis-plus鏈式調(diào)用的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)mybatis-plus鏈式調(diào)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MybatisPlus調(diào)用原生SQL的三種方法實例詳解
- 解決mybatis-plus通用mapper調(diào)用報錯:Invalid bound statement
- MybatisPlus如何調(diào)用count函數(shù)
- mybatis-plus調(diào)用update方法時,自動填充字段不生效問題及解決
- java的MybatisPlus調(diào)用儲存過程的返回數(shù)據(jù)問題
- MybatisPlus中如何調(diào)用Oracle存儲過程
- 調(diào)用Mybatis?plus中的saveBatch方法報找不到表的問題
- MybatisPlus調(diào)用原生SQL的實現(xiàn)方法
- 模仿mybatis-plus實現(xiàn)rpc調(diào)用
相關(guān)文章
SpringBoot+WebSocket+Netty實現(xiàn)消息推送的示例代碼
這篇文章主要介紹了SpringBoot+WebSocket+Netty實現(xiàn)消息推送的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-04-04
詳解Java?SSM項目部署上線配置方法(阿里云服務器ECS?+?云數(shù)據(jù)庫RDS?MySQL)(寶塔)
這篇文章主要介紹了Java?SSM項目部署上線(阿里云服務器ECS?+?云數(shù)據(jù)庫RDS?MySQL)(寶塔)的圖文教程,本文通過圖文并茂的形式給大家介紹的非常詳細,感興趣的朋友一起看看吧2024-01-01
springboot項目開啟https協(xié)議的項目實現(xiàn)
本文主要介紹了springboot項目開啟https協(xié)議的項目實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-07-07
Spring構(gòu)造器注入及@Autowired、lombok的@RequiredArgsConstructor的異同點說明
本文介紹了Spring框架中構(gòu)造器注入的實現(xiàn)原理,包括Spring如何找到參數(shù)、構(gòu)造器注入與Autowired的區(qū)別,以及為什么Spring官方推薦構(gòu)造器注入,文章還強調(diào)了構(gòu)造器注入中使用final關(guān)鍵字的好處,并提供了代碼示例,幫助讀者更好地理解和應用Spring的最佳實踐2026-03-03
SpringBoot后端接口的實現(xiàn)(看這一篇就夠了)
這篇文章主要介紹了SpringBoot后端接口的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-09-09
java實現(xiàn)多線程的兩種方式繼承Thread類和實現(xiàn)Runnable接口的方法
下面小編就為大家?guī)硪黄猨ava實現(xiàn)多線程的兩種方式繼承Thread類和實現(xiàn)Runnable接口的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09

