mybatis-plus链式调用的实现示例
mybatis-plus相信大家都不陌生,尤其在需要快速开发的时候,使用mp进行开发,确实能提高效率,在使用的过程中,一直都很好奇,mp是如何实现链式调用的
源码解析
从最经典的LambdaQueryWrapper入手,点开源码会发现,调用的函数返回了typedThis,确实是很经典的链式的设计,所谓链式调用,就是通过设置方法的返回值,让返回值变为对象自身,从而实现连续的方法调用
public class LambdaQueryWrapper<T> extends AbstractLambdaWrapper<T, LambdaQueryWrapper<T>>
implements Query<LambdaQueryWrapper<T>, T, SFunction<T, ?>> {
// 省略构造函数
/**
* SELECT 部分 SQL 设置
*
* @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,会发现来到了AbstractWrapper中,看来这里就是真正实现链式调用的地方,看到这里原谅我孤陋寡闻,确实没怎么用泛型,原来还能这么用的😂。
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,用来实现方法的引用
@Override
public Children eq(boolean condition, R column, Object val) {
return addCondition(condition, column, EQ, val);
}
T,R其实都是泛型占位符,T大家应该都见过很多了,但为什么还有一个R呢?查看一下AbstractWrapper的实现类,会发现正常的query指定的是string,而lambdaquery指定的是SFunction<T, ?>,看来是实现lambdaquery的方法引用,具体的实现可以查看一下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也是同理,是一个自引用的占位符,根据不同的子类实现,强转成不同的子类示例
自定义实现
知道了原理,就可以模仿一下mp的实现,先定义一个抽象类,业务没那么复杂,就不需要定义太多泛型,同时定义一些方法和抽象方法
@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;
}
}
这样就实现了一个简易的链式调用方法了

总结
总的来说,mp通过在父类定义一个自引用的泛型来实现链式调用,之后继承该父类的子类,只要重写父类定义的方法,既可实现链式调用,同时又定义了多个泛型类型,子类根据不同的业务需求,自定义方法的入参和出参。对于泛型的使用是一个很好的例子
到此这篇关于mybatis-plus链式调用的实现示例的文章就介绍到这了,更多相关mybatis-plus链式调用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
SpringBoot+WebSocket+Netty实现消息推送的示例代码
这篇文章主要介绍了SpringBoot+WebSocket+Netty实现消息推送的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-04-04
详解Java SSM项目部署上线配置方法(阿里云服务器ECS + 云数据库RDS MySQL)(宝塔)
这篇文章主要介绍了Java SSM项目部署上线(阿里云服务器ECS + 云数据库RDS MySQL)(宝塔)的图文教程,本文通过图文并茂的形式给大家介绍的非常详细,感兴趣的朋友一起看看吧2024-01-01
Spring构造器注入及@Autowired、lombok的@RequiredArgsConstructor的异同点说明
本文介绍了Spring框架中构造器注入的实现原理,包括Spring如何找到参数、构造器注入与Autowired的区别,以及为什么Spring官方推荐构造器注入,文章还强调了构造器注入中使用final关键字的好处,并提供了代码示例,帮助读者更好地理解和应用Spring的最佳实践2026-03-03
java实现多线程的两种方式继承Thread类和实现Runnable接口的方法
下面小编就为大家带来一篇java实现多线程的两种方式继承Thread类和实现Runnable接口的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧2016-09-09


最新评论