mirror of
https://gitee.com/best_handsome/mybatis-plus-join
synced 2025-07-11 00:02:22 +08:00
连表查询ON语句支持多条件,以及where支持字段与字段的条件(a.id = b.a_id)这样的写法
This commit is contained in:
parent
2fdd0e5e6f
commit
722821e0f0
@ -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)));
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 不等于 <>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 大于 >
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 大于等于 >=
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 小于 <
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 小于等于 <=
|
||||
*
|
||||
* @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);
|
||||
}
|
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user