连表查询ON语句支持多条件,以及where支持字段与字段的条件(a.id = b.a_id)这样的写法

This commit is contained in:
admin 2021-05-28 17:22:28 +08:00
parent 2fdd0e5e6f
commit 722821e0f0
5 changed files with 306 additions and 52 deletions

View File

@ -15,6 +15,7 @@ import com.github.yulichang.toolkit.sql.SqlScriptUtils;
import com.github.yulichang.wrapper.interfaces.Compare;
import com.github.yulichang.wrapper.interfaces.Func;
import com.github.yulichang.wrapper.interfaces.Join;
import com.github.yulichang.wrapper.interfaces.on.OnCompare;
import java.util.Arrays;
import java.util.Collection;
@ -34,9 +35,9 @@ import static java.util.stream.Collectors.joining;
*
* @author yulichang
*/
@SuppressWarnings({"serial", "unchecked"})
@SuppressWarnings("ALL")
public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<T, Children>> extends Wrapper<T>
implements Compare<Children>, Nested<Children, Children>, Join<Children>, Func<Children> {
implements Compare<Children>, Nested<Children, Children>, Join<Children>, Func<Children>, OnCompare<Children> {
/**
* 占位符
@ -383,6 +384,11 @@ public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<
() -> formatParam(null, val)));
}
protected <X, S> Children addCondition(boolean condition, SFunction<X, ?> column, SqlKeyword sqlKeyword, SFunction<S, ?> val) {
return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), sqlKeyword,
columnToSqlSegment(val)));
}
/**
* 多重嵌套查询条件
*
@ -596,4 +602,68 @@ public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<
void doIt();
}
/* ************************* on语句重载 *************************** */
@Override
public <R, S> Children eq(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val) {
return addCondition(condition, column, EQ, val);
}
@Override
public <R, S> Children ne(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val) {
return addCondition(condition, column, NE, val);
}
@Override
public <R, S> Children gt(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val) {
return addCondition(condition, column, GT, val);
}
@Override
public <R, S> Children ge(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val) {
return addCondition(condition, column, GE, val);
}
@Override
public <R, S> Children lt(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val) {
return addCondition(condition, column, LT, val);
}
@Override
public <R, S> Children le(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val) {
return addCondition(condition, column, LE, val);
}
@Override
public <R, S, U> Children between(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val1, SFunction<U, ?> val2) {
return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), BETWEEN,
columnToSqlSegment(val1), AND, columnToSqlSegment(val2)));
}
public <R, S> Children between(boolean condition, SFunction<R, ?> column, Object val1, SFunction<S, ?> val2) {
return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), BETWEEN,
() -> formatParam(null, val1), AND, columnToSqlSegment(val2)));
}
public <R, S> Children between(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val1, Object val2) {
return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), BETWEEN,
columnToSqlSegment(val1), AND, () -> formatParam(null, val2)));
}
@Override
public <R, S, U> Children notBetween(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val1, SFunction<U, ?> val2) {
return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), NOT_BETWEEN,
columnToSqlSegment(val1), AND, columnToSqlSegment(val2)));
}
public <R, U> Children notBetween(boolean condition, SFunction<R, ?> column, Object val1, SFunction<U, ?> val2) {
return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), NOT_BETWEEN,
() -> formatParam(null, val1), AND, columnToSqlSegment(val2)));
}
public <R, S> Children notBetween(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val1, Object val2) {
return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), NOT_BETWEEN,
columnToSqlSegment(val1), AND, () -> formatParam(null, val2)));
}
}

View File

@ -8,9 +8,11 @@ import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.toolkit.Constant;
import com.github.yulichang.toolkit.LambdaUtils;
import com.github.yulichang.wrapper.interfaces.LambdaJoin;
import com.github.yulichang.wrapper.interfaces.SFunctionQuery;
import com.github.yulichang.wrapper.interfaces.on.OnFunction;
import lombok.Data;
import lombok.Getter;
import java.util.ArrayList;
import java.util.List;
@ -63,6 +65,23 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
*/
private int tableIndex = 1;
/**
* ON sql wrapper集合
*/
private final List<MPJLambdaWrapper<?>> onWrappers = new ArrayList<>();
/**
* 连表关键字 on 条件 func 使用
*/
@Getter
private String keyWord;
/**
* 连表实体类 on 条件 func 使用
*/
@Getter
private Class<?> joinClass;
/**
* 不建议直接 new 该实例使用 Wrappers.lambdaQuery()
*/
@ -70,13 +89,14 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
super.initNeed();
}
/**
* 不建议直接 new 该实例使用 Wrappers.lambdaQuery(...)
*/
MPJLambdaWrapper(T entity, Class<T> entityClass, SharedString sqlSelect, AtomicInteger paramNameSeq,
Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments,
SharedString lastSql, SharedString sqlComment, SharedString sqlFirst,
Map<Class<?>, Integer> subTable) {
Map<Class<?>, Integer> subTable, String keyWord, Class<?> joinClass) {
super.setEntity(entity);
super.setEntityClass(entityClass);
this.paramNameSeq = paramNameSeq;
@ -87,6 +107,8 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
this.sqlComment = sqlComment;
this.sqlFirst = sqlFirst;
this.subTable = subTable;
this.keyWord = keyWord;
this.joinClass = joinClass;
}
/**
@ -174,6 +196,19 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
public String getFrom() {
if (StringUtils.isBlank(from.getStringValue())) {
StringBuilder value = new StringBuilder();
for (MPJLambdaWrapper<?> wrapper : onWrappers) {
String tableName = TableInfoHelper.getTableInfo(wrapper.getJoinClass()).getTableName();
value.append(wrapper.getKeyWord())
.append(tableName)
.append(Constant.SPACE_TABLE_ALIAS)
.append(subTable.get(wrapper.getJoinClass()))
.append(Constant.ON)
.append(wrapper.getExpression().getNormal().getSqlSegment());
}
from.setStringValue(value.toString());
}
return from.getStringValue();
}
@ -187,9 +222,13 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
*/
@Override
protected MPJLambdaWrapper<T> instance() {
return instance(null, null);
}
protected MPJLambdaWrapper<T> instance(String keyWord, Class<?> joinClass) {
return new MPJLambdaWrapper<>(getEntity(), getEntityClass(), null, paramNameSeq, paramNameValuePairs,
new MergeSegments(), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(),
this.subTable);
this.subTable, keyWord, joinClass);
}
@Override
@ -199,28 +238,13 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
}
@Override
public <L, X> MPJLambdaWrapper<T> join(String keyWord, boolean condition, Class<L> clazz, SFunction<L, ?> left, SFunction<X, ?> right) {
public <R> MPJLambdaWrapper<T> join(String keyWord, boolean condition, Class<R> clazz, OnFunction function) {
if (condition) {
MPJLambdaWrapper<?> apply = function.apply(instance(keyWord, clazz));
onWrappers.add(apply);
subTable.put(clazz, tableIndex);
TableInfo leftInfo = TableInfoHelper.getTableInfo(clazz);
StringBuilder sb = new StringBuilder(keyWord)
.append(leftInfo.getTableName())
.append(Constant.SPACE_TABLE_ALIAS)
.append(tableIndex)
.append(Constant.ON_TABLE_ALIAS)
.append(tableIndex)
.append(StringPool.DOT)
.append(getCache(left).getColumn())
.append(Constant.EQUALS_TABLE_ALIAS)
.append(getDefault(subTable.get(LambdaUtils.getEntityClass(right))))
.append(StringPool.DOT)
.append(getCache(right).getColumn());
tableIndex++;
if (StringUtils.isBlank(from.getStringValue())) {
from.setStringValue(sb.toString());
} else {
from.setStringValue(from.getStringValue() + sb.toString());
}
}
return typedThis;
}
@ -228,6 +252,7 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
/**
* select字段
*/
@Data
public static class SelectColumn {
private Class<?> clazz;
@ -241,29 +266,5 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
this.columnName = columnName;
this.alias = alias;
}
public Class<?> getClazz() {
return clazz;
}
public void setClazz(Class<?> clazz) {
this.clazz = clazz;
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
}
}

View File

@ -3,6 +3,7 @@ package com.github.yulichang.wrapper.interfaces;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.interfaces.MPJBaseJoin;
import com.github.yulichang.toolkit.Constant;
import com.github.yulichang.wrapper.interfaces.on.OnFunction;
/**
* @author yulichang
@ -13,27 +14,49 @@ public interface LambdaJoin<Children> extends MPJBaseJoin {
return leftJoin(true, clazz, left, right);
}
default <T> Children leftJoin(Class<T> clazz, OnFunction function) {
return leftJoin(true, clazz, function);
}
default <T, X> Children leftJoin(boolean condition, Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right) {
return join(Constant.LEFT_JOIN, condition, clazz, left, right);
return leftJoin(condition, clazz, on -> on.eq(left, right));
}
default <T> Children leftJoin(boolean condition, Class<T> clazz, OnFunction function) {
return join(Constant.LEFT_JOIN, condition, clazz, function);
}
default <T, X> Children rightJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right) {
return rightJoin(true, clazz, left, right);
}
default <T> Children rightJoin(Class<T> clazz, OnFunction function) {
return rightJoin(true, clazz, function);
}
default <T, X> Children rightJoin(boolean condition, Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right) {
return join(Constant.RIGHT_JOIN, condition, clazz, left, right);
return rightJoin(condition, clazz, on -> on.eq(left, right));
}
default <T> Children rightJoin(boolean condition, Class<T> clazz, OnFunction function) {
return join(Constant.RIGHT_JOIN, condition, clazz, function);
}
default <T, X> Children innerJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right) {
return innerJoin(true, clazz, left, right);
}
default <T> Children innerJoin(Class<T> clazz, OnFunction function) {
return innerJoin(true, clazz, function);
}
default <T, X> Children innerJoin(boolean condition, Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right) {
return join(Constant.INNER_JOIN, condition, clazz, left, right);
return innerJoin(condition, clazz, on -> on.eq(left, right));
}
<T, X> Children join(String keyWord, boolean condition, Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right);
default <T> Children innerJoin(boolean condition, Class<T> clazz, OnFunction function) {
return join(Constant.INNER_JOIN, condition, clazz, function);
}
<T> Children join(String keyWord, boolean condition, Class<T> clazz, OnFunction function);
}

View File

@ -0,0 +1,151 @@
package com.github.yulichang.wrapper.interfaces.on;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import java.io.Serializable;
/**
* 将原来的泛型R改成SFunction<R, ?>, Object改为SFunction<S, ?>
* 以及移除不会在ON语句中出现的条件 比如like相关 保留原来的like 只是不太可能会出现 on a.id like b.id 所以不会支持这种写法
* <p>
* {@link com.baomidou.mybatisplus.core.conditions.interfaces.Compare}
*/
public interface OnCompare<Children> extends Serializable {
/**
* ignore
*/
default <R, S> Children eq(SFunction<R, ?> column, SFunction<S, ?> val) {
return eq(true, column, val);
}
/**
* 等于 =
*
* @param condition 执行条件
* @param column 字段
* @param val
* @return children
*/
<R, S> Children eq(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val);
/**
* ignore
*/
default <R, S> Children ne(SFunction<R, ?> column, SFunction<S, ?> val) {
return ne(true, column, val);
}
/**
* 不等于 &lt;&gt;
*
* @param condition 执行条件
* @param column 字段
* @param val
* @return children
*/
<R, S> Children ne(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val);
/**
* ignore
*/
default <R, S> Children gt(SFunction<R, ?> column, SFunction<S, ?> val) {
return gt(true, column, val);
}
/**
* 大于 &gt;
*
* @param condition 执行条件
* @param column 字段
* @param val
* @return children
*/
<R, S> Children gt(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val);
/**
* ignore
*/
default <R, S> Children ge(SFunction<R, ?> column, SFunction<S, ?> val) {
return ge(true, column, val);
}
/**
* 大于等于 &gt;=
*
* @param condition 执行条件
* @param column 字段
* @param val
* @return children
*/
<R, S> Children ge(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val);
/**
* ignore
*/
default <R, S> Children lt(SFunction<R, ?> column, SFunction<S, ?> val) {
return lt(true, column, val);
}
/**
* 小于 &lt;
*
* @param condition 执行条件
* @param column 字段
* @param val
* @return children
*/
<R, S> Children lt(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val);
/**
* ignore
*/
default <R, S> Children le(SFunction<R, ?> column, SFunction<S, ?> val) {
return le(true, column, val);
}
/**
* 小于等于 &lt;=
*
* @param condition 执行条件
* @param column 字段
* @param val
* @return children
*/
<R, S> Children le(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val);
/**
* ignore
*/
default <R, S, T> Children between(SFunction<R, ?> column, SFunction<S, ?> val1, SFunction<T, ?> val2) {
return between(true, column, val1, val2);
}
/**
* BETWEEN 值1 AND 值2
*
* @param condition 执行条件
* @param column 字段
* @param val1 值1
* @param val2 值2
* @return children
*/
<R, S, T> Children between(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val1, SFunction<T, ?> val2);
/**
* ignore
*/
default <R, S, T> Children notBetween(SFunction<R, ?> column, SFunction<S, ?> val1, SFunction<T, ?> val2) {
return notBetween(true, column, val1, val2);
}
/**
* NOT BETWEEN 值1 AND 值2
*
* @param condition 执行条件
* @param column 字段
* @param val1 值1
* @param val2 值2
* @return children
*/
<R, S, T> Children notBetween(boolean condition, SFunction<R, ?> column, SFunction<S, ?> val1, SFunction<T, ?> val2);
}

View File

@ -0,0 +1,9 @@
package com.github.yulichang.wrapper.interfaces.on;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
@FunctionalInterface
public interface OnFunction {
MPJLambdaWrapper<?> apply(MPJLambdaWrapper<?> wrapper);
}