以下所有代码和观点来源均为
org.mybatis.spring.boot mybatis-spring-boot-starter 2.0.1
mybatis-plus 作为一个强大的 mybatis阵营的orm框架,很多功能已经用的飞起,但是呢在查询方面还是欠缺部分api,比如要进行如下查询时无法用到 lamdba表达式
select min(column) as n from table
这时候是无法用自带的LambdaQueryWrapper实现的,此时就需要我们手动改造下
分析源码核心源码其实就两个方法一个属性
// 存放sql语句 private SharedString sqlSelect = new SharedString(); @SafeVarargs @Override public final LambdaQueryWrapperselect(SFunction ... columns) { if (ArrayUtils.isNotEmpty(columns)) { this.sqlSelect.setStringValue(columnsToString(false, columns)); } return typedThis; } @Override public String getSqlSelect() { return sqlSelect.getStringValue(); }
SharedString 这个类本质上也是一个string只是多了几个方法而已
public class SharedString implements Serializable {
private static final long serialVersionUID = -1536422416594422874L;
private String stringValue;
public static SharedString emptyString() {
return new SharedString(StringPool.EMPTY);
}
public void toEmpty() {
stringValue = StringPool.EMPTY;
}
public void toNull() {
stringValue = null;
}
}
所以在使用中多个字段的查询不能函数调用
改造此时我们自己实现 LambdaQueryWrapper,然后将SharedString 改成一个由list实现的类
自定义的LambdaQueryWrapper 命名为 MyLambdaQueryWrapper
public class MyLambdaQueryWrapperextends AbstractLambdaWrapper > implements Query , T, SFunction > { private SelectBuilder sqlSelect = new SelectBuilder(); public MyLambdaQueryWrapper() { this((T) null); } public MyLambdaQueryWrapper(T entity) { super.setEntity(entity); super.initNeed(); } public MyLambdaQueryWrapper(Class entityClass) { super.setEntityClass(entityClass); super.initNeed(); } MyLambdaQueryWrapper(T entity, Class entityClass, SelectBuilder sqlSelect, AtomicInteger paramNameSeq, Map paramNamevaluePairs, MergeSegments mergeSegments, SharedString lastSql, SharedString sqlComment, SharedString sqlFirst) { super.setEntity(entity); super.setEntityClass(entityClass); this.paramNameSeq = paramNameSeq; this.paramNamevaluePairs = paramNamevaluePairs; this.expression = mergeSegments; this.sqlSelect = sqlSelect; this.lastSql = lastSql; this.sqlComment = sqlComment; this.sqlFirst = sqlFirst; } @SafeVarargs @Override public final MyLambdaQueryWrapper select(SFunction ... columns) { if (ArrayUtils.isNotEmpty(columns)) { this.sqlSelect.getParts().add(columnsToString(columns)); } return typedThis; } @Override public MyLambdaQueryWrapper select(Class entityClass, Predicate predicate) { if (entityClass == null) { entityClass = getEntityClass(); } else { setEntityClass(entityClass); } Assert.notNull(entityClass, "entityClass can not be null"); this.sqlSelect.getParts().add(TableInfoHelper.getTableInfo(entityClass).chooseSelect(predicate)); return typedThis; } @Override public String getSqlSelect() { return sqlSelect.getStringValue(); } @Override protected MyLambdaQueryWrapper instance() { return new MyLambdaQueryWrapper<>(getEntity(), getEntityClass(), null, paramNameSeq, paramNamevaluePairs, new MergeSegments(), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString()); } @Override public void clear() { super.clear(); sqlSelect.toNull(); } // =================== 上面的代码都是照抄的 ===================== public MyLambdaQueryWrapper min(SFunction column){ if (column != null) { this.sqlSelect.getParts().add(String.format("min(%s)", columnToString(column))); } return typedThis; } public MyLambdaQueryWrapper max(SFunction column){ if (column != null) { this.sqlSelect.getParts().add(String.format("max(%s)", columnToString(column))); } return typedThis; } public MyLambdaQueryWrapper sum(SFunction column){ if (column != null) { this.sqlSelect.getParts().add(String.format("sum(%s)", columnToString(column))); } return typedThis; } public MyLambdaQueryWrapper as(String asName){ if (StringUtils.isEmpty(asName)) { return typedThis; } List parts = this.sqlSelect.getParts(); if (CollectionUtil.isEmpty(parts)) { return typedThis; } String lastPart = parts.remove(parts.size() - 1); lastPart += " as " + asName; parts.add(lastPart); return typedThis; } }
还有一个暂存查询列的list组装对象
@Getter
@Setter
public class SelectBuilder implements Serializable {
private static final long serialVersionUID = -1536422416594422874L;
private List parts;
public SelectBuilder() {
this.parts = new ArrayList<>();
}
public void toEmpty() {
parts.clear();
}
public void toNull() {
parts = null;
}
public String getStringValue(){
if (CollectionUtil.isNotEmpty(parts)) {
return String.join(",", parts);
}else {
return null;
}
}
}
使用代码
MyLambdaQueryWrappermyLambdaQuery = getMyLambdaQuery(); myLambdaQuery.min(SignConfig::getLongitude).as("logg"); myLambdaQuery.sum(SignConfig::getLongitude).as("lo"); return baseMapper.selectObjs(myLambdaQuery);
对应的sql
SELECT min(longitude) as logg,sum(longitude) as lo FROM work_sign_config



