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

mybatis-plus鏈?zhǔn)秸{(diào)用的實(shí)現(xiàn)示例

 更新時(shí)間:2026年02月18日 09:12:54   作者:9號(hào)達(dá)人  
MyBatis-Plus如何實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用?通過源碼解析,我們發(fā)現(xiàn)它利用泛型和自引用的抽象類來實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,父類定義了一個(gè)自引用的泛型,子類繼承并重寫方法,即可實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,同時(shí)也定義了多種泛型類型,需要的朋友可以參考下

mybatis-plus相信大家都不陌生,尤其在需要快速開發(fā)的時(shí)候,使用mp進(jìn)行開發(fā),確實(shí)能提高效率,在使用的過程中,一直都很好奇,mp是如何實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用的

源碼解析

從最經(jīng)典的LambdaQueryWrapper入手,點(diǎn)開源碼會(huì)發(fā)現(xiàn),調(diào)用的函數(shù)返回了typedThis,確實(shí)是很經(jīng)典的鏈?zhǔn)降脑O(shè)計(jì),所謂鏈?zhǔn)秸{(diào)用,就是通過設(shè)置方法的返回值,讓返回值變?yōu)閷?duì)象自身,從而實(shí)現(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,會(huì)發(fā)現(xiàn)來到了AbstractWrapper中,看來這里就是真正實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用的地方,看到這里原諒我孤陋寡聞,確實(shí)沒怎么用泛型,原來還能這么用的??。

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,用來實(shí)現(xiàn)方法的引用
    @Override
    public Children eq(boolean condition, R column, Object val) {
        return addCondition(condition, column, EQ, val);
    }

T,R其實(shí)都是泛型占位符,T大家應(yīng)該都見過很多了,但為什么還有一個(gè)R呢?查看一下AbstractWrapper的實(shí)現(xiàn)類,會(huì)發(fā)現(xiàn)正常的query指定的是string,而lambdaquery指定的是SFunction<T, ?>,看來是實(shí)現(xiàn)lambdaquery的方法引用,具體的實(shí)現(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也是同理,是一個(gè)自引用的占位符,根據(jù)不同的子類實(shí)現(xiàn),強(qiáng)轉(zhuǎn)成不同的子類示例

自定義實(shí)現(xiàn)

知道了原理,就可以模仿一下mp的實(shí)現(xiàn),先定義一個(gè)抽象類,業(yè)務(wù)沒那么復(fù)雜,就不需要定義太多泛型,同時(shí)定義一些方法和抽象方法

@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;
    }
}

這樣就實(shí)現(xiàn)了一個(gè)簡(jiǎn)易的鏈?zhǔn)秸{(diào)用方法了

總結(jié)

總的來說,mp通過在父類定義一個(gè)自引用的泛型來實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,之后繼承該父類的子類,只要重寫父類定義的方法,既可實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,同時(shí)又定義了多個(gè)泛型類型,子類根據(jù)不同的業(yè)務(wù)需求,自定義方法的入?yún)⒑统鰠ⅰ?duì)于泛型的使用是一個(gè)很好的例子

‍到此這篇關(guān)于mybatis-plus鏈?zhǔn)秸{(diào)用的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)mybatis-plus鏈?zhǔn)秸{(diào)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

姜堰市| 醴陵市| 西乌| 长葛市| 罗定市| 杭锦后旗| 宣汉县| 台州市| 锦屏县| 新源县| 四会市| 沙田区| 安达市| 武陟县| 永善县| 台南县| 乐亭县| 榆社县| 沧源| 绥德县| 曲麻莱县| 锡林浩特市| 清水县| 静海县| 类乌齐县| 新乡市| 遂溪县| 鹰潭市| 桦南县| 深州市| 攀枝花市| 南岸区| 海盐县| 涟水县| 新平| 漯河市| 读书| 秭归县| 凯里市| 崇礼县| 吉安县|