mirror of
https://gitee.com/best_handsome/mybatis-plus-join
synced 2025-07-11 00:02:22 +08:00
update to stater
This commit is contained in:
parent
5834794ac5
commit
61071d49e3
@ -1,54 +0,0 @@
|
||||
package com.github.yulichang.common;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.toolkit.LambdaUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
/**
|
||||
* copy {@link com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper}
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class JoinAbstractLambdaWrapper<T, Children extends JoinAbstractLambdaWrapper<T, Children>>
|
||||
extends JoinAbstractWrapper<T, Children> {
|
||||
|
||||
protected final Map<Class<?>, String> subTable = new HashMap<>();
|
||||
|
||||
@Override
|
||||
protected <X> String columnToString(X column) {
|
||||
return columnToString((SFunction<?, ?>) column, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <X> String columnsToString(X... columns) {
|
||||
return Arrays.stream(columns).map(i -> columnToString((SFunction<?, ?>) i, true)).collect(joining(StringPool.COMMA));
|
||||
}
|
||||
|
||||
protected String columnToString(SFunction<?, ?> column, boolean onlyColumn) {
|
||||
return getDefault(LambdaUtils.getEntityClass(column)) + StringPool.DOT +
|
||||
LambdaUtils.getColumn(column);
|
||||
}
|
||||
|
||||
protected String getDefault(Class<?> clazz) {
|
||||
String alias = subTable.get(clazz);
|
||||
if (StringUtils.isNotBlank(alias)) {
|
||||
return alias;
|
||||
}
|
||||
TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
|
||||
Assert.notNull(tableInfo, "can not find table");
|
||||
return tableInfo.getTableName();
|
||||
}
|
||||
|
||||
}
|
@ -1,513 +0,0 @@
|
||||
package com.github.yulichang.common;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.ISqlSegment;
|
||||
import com.baomidou.mybatisplus.core.conditions.SharedString;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.interfaces.Join;
|
||||
import com.baomidou.mybatisplus.core.conditions.interfaces.Nested;
|
||||
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
|
||||
import com.baomidou.mybatisplus.core.enums.SqlLike;
|
||||
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.StringEscape;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.wrapper.interfaces.Compare;
|
||||
import com.github.yulichang.wrapper.interfaces.Func;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static com.baomidou.mybatisplus.core.enums.SqlKeyword.*;
|
||||
import static com.baomidou.mybatisplus.core.enums.WrapperKeyword.APPLY;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
/**
|
||||
* copy {@link com.baomidou.mybatisplus.core.conditions.AbstractWrapper}
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
@SuppressWarnings({"serial", "unchecked"})
|
||||
public abstract class JoinAbstractWrapper<T, Children extends JoinAbstractWrapper<T, Children>> extends Wrapper<T>
|
||||
implements Compare<Children>, Nested<Children, Children>, Join<Children>, Func<Children> {
|
||||
|
||||
/**
|
||||
* 占位符
|
||||
*/
|
||||
protected final Children typedThis = (Children) this;
|
||||
/**
|
||||
* 必要度量
|
||||
*/
|
||||
protected AtomicInteger paramNameSeq;
|
||||
protected Map<String, Object> paramNameValuePairs;
|
||||
protected SharedString lastSql;
|
||||
/**
|
||||
* SQL注释
|
||||
*/
|
||||
protected SharedString sqlComment;
|
||||
/**
|
||||
* SQL起始语句
|
||||
*/
|
||||
protected SharedString sqlFirst;
|
||||
/**
|
||||
* ß
|
||||
* 数据库表映射实体类
|
||||
*/
|
||||
private T entity;
|
||||
protected MergeSegments expression;
|
||||
/**
|
||||
* 实体类型(主要用于确定泛型以及取TableInfo缓存)
|
||||
*/
|
||||
private Class<T> entityClass;
|
||||
|
||||
@Override
|
||||
public T getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
public Children setEntity(T entity) {
|
||||
this.entity = entity;
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
public Class<T> getEntityClass() {
|
||||
if (entityClass == null && entity != null) {
|
||||
entityClass = (Class<T>) entity.getClass();
|
||||
}
|
||||
return entityClass;
|
||||
}
|
||||
|
||||
public Children setEntityClass(Class<T> entityClass) {
|
||||
if (entityClass != null) {
|
||||
this.entityClass = entityClass;
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X, V> Children allEq(boolean condition, Map<SFunction<X, ?>, V> params, boolean null2IsNull) {
|
||||
if (condition && CollectionUtils.isNotEmpty(params)) {
|
||||
params.forEach((k, v) -> {
|
||||
if (StringUtils.checkValNotNull(v)) {
|
||||
eq(k, v);
|
||||
} else {
|
||||
if (null2IsNull) {
|
||||
isNull(k);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X, V> Children allEq(boolean condition, BiPredicate<SFunction<X, ?>, V> filter, Map<SFunction<X, ?>, V> params, boolean null2IsNull) {
|
||||
if (condition && CollectionUtils.isNotEmpty(params)) {
|
||||
params.forEach((k, v) -> {
|
||||
if (filter.test(k, v)) {
|
||||
if (StringUtils.checkValNotNull(v)) {
|
||||
eq(k, v);
|
||||
} else {
|
||||
if (null2IsNull) {
|
||||
isNull(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children eq(boolean condition, SFunction<X, ?> column, Object val) {
|
||||
return addCondition(condition, column, EQ, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children ne(boolean condition, SFunction<X, ?> column, Object val) {
|
||||
return addCondition(condition, column, NE, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children gt(boolean condition, SFunction<X, ?> column, Object val) {
|
||||
return addCondition(condition, column, GT, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children ge(boolean condition, SFunction<X, ?> column, Object val) {
|
||||
return addCondition(condition, column, GE, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children lt(boolean condition, SFunction<X, ?> column, Object val) {
|
||||
return addCondition(condition, column, LT, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children le(boolean condition, SFunction<X, ?> column, Object val) {
|
||||
return addCondition(condition, column, LE, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children like(boolean condition, SFunction<X, ?> column, Object val) {
|
||||
return likeValue(condition, LIKE, column, val, SqlLike.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children notLike(boolean condition, SFunction<X, ?> column, Object val) {
|
||||
return likeValue(condition, NOT_LIKE, column, val, SqlLike.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children likeLeft(boolean condition, SFunction<X, ?> column, Object val) {
|
||||
return likeValue(condition, LIKE, column, val, SqlLike.LEFT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children likeRight(boolean condition, SFunction<X, ?> column, Object val) {
|
||||
return likeValue(condition, LIKE, column, val, SqlLike.RIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children between(boolean condition, SFunction<X, ?> column, Object val1, Object val2) {
|
||||
return doIt(condition, () -> columnToString(column), BETWEEN, () -> formatSql("{0}", val1), AND,
|
||||
() -> formatSql("{0}", val2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children notBetween(boolean condition, SFunction<X, ?> column, Object val1, Object val2) {
|
||||
return doIt(condition, () -> columnToString(column), NOT_BETWEEN, () -> formatSql("{0}", val1), AND,
|
||||
() -> formatSql("{0}", val2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children and(boolean condition, Consumer<Children> consumer) {
|
||||
return and(condition).addNestedCondition(condition, consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children or(boolean condition, Consumer<Children> consumer) {
|
||||
return or(condition).addNestedCondition(condition, consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children nested(boolean condition, Consumer<Children> consumer) {
|
||||
return addNestedCondition(condition, consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children not(boolean condition, Consumer<Children> consumer) {
|
||||
return not(condition).addNestedCondition(condition, consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children or(boolean condition) {
|
||||
return doIt(condition, OR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children apply(boolean condition, String applySql, Object... value) {
|
||||
return doIt(condition, APPLY, () -> formatSql(applySql, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children last(boolean condition, String lastSql) {
|
||||
if (condition) {
|
||||
this.lastSql.setStringValue(StringPool.SPACE + lastSql);
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children comment(boolean condition, String comment) {
|
||||
if (condition) {
|
||||
this.sqlComment.setStringValue(comment);
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children first(boolean condition, String firstSql) {
|
||||
if (condition) {
|
||||
this.sqlFirst.setStringValue(firstSql);
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children exists(boolean condition, String existsSql) {
|
||||
return doIt(condition, EXISTS, () -> String.format("(%s)", existsSql));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children notExists(boolean condition, String existsSql) {
|
||||
return not(condition).exists(condition, existsSql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children isNull(boolean condition, SFunction<X, ?> column) {
|
||||
return doIt(condition, () -> columnToString(column), IS_NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children isNotNull(boolean condition, SFunction<X, ?> column) {
|
||||
return doIt(condition, () -> columnToString(column), IS_NOT_NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children in(boolean condition, SFunction<X, ?> column, Collection<?> coll) {
|
||||
return doIt(condition, () -> columnToString(column), IN, inExpression(coll));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children notIn(boolean condition, SFunction<X, ?> column, Collection<?> coll) {
|
||||
return doIt(condition, () -> columnToString(column), NOT_IN, inExpression(coll));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children inSql(boolean condition, SFunction<X, ?> column, String inValue) {
|
||||
return doIt(condition, () -> columnToString(column), IN, () -> String.format("(%s)", inValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children notInSql(boolean condition, SFunction<X, ?> column, String inValue) {
|
||||
return doIt(condition, () -> columnToString(column), NOT_IN, () -> String.format("(%s)", inValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children groupBy(boolean condition, SFunction<X, ?>... columns) {
|
||||
if (ArrayUtils.isEmpty(columns)) {
|
||||
return typedThis;
|
||||
}
|
||||
return doIt(condition, GROUP_BY,
|
||||
() -> columns.length == 1 ? columnToString(columns[0]) : columnsToString(columns));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Children orderBy(boolean condition, boolean isAsc, SFunction<X, ?>... columns) {
|
||||
if (ArrayUtils.isEmpty(columns)) {
|
||||
return typedThis;
|
||||
}
|
||||
SqlKeyword mode = isAsc ? ASC : DESC;
|
||||
for (SFunction<X, ?> column : columns) {
|
||||
doIt(condition, ORDER_BY, () -> columnToString(column), mode);
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children having(boolean condition, String sqlHaving, Object... params) {
|
||||
return doIt(condition, HAVING, () -> formatSqlIfNeed(condition, sqlHaving, params));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children func(boolean condition, Consumer<Children> consumer) {
|
||||
if (condition) {
|
||||
consumer.accept(typedThis);
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部自用
|
||||
* <p>NOT 关键词</p>
|
||||
*/
|
||||
protected Children not(boolean condition) {
|
||||
return doIt(condition, NOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部自用
|
||||
* <p>拼接 AND</p>
|
||||
*/
|
||||
protected Children and(boolean condition) {
|
||||
return doIt(condition, AND);
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部自用
|
||||
* <p>拼接 LIKE 以及 值</p>
|
||||
*/
|
||||
protected <X> Children likeValue(boolean condition, SqlKeyword keyword, SFunction<X, ?> column, Object val, SqlLike sqlLike) {
|
||||
return doIt(condition, () -> columnToString(column), keyword, () -> formatSql("{0}", SqlUtils.concatLike(val, sqlLike)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通查询条件
|
||||
*
|
||||
* @param condition 是否执行
|
||||
* @param column 属性
|
||||
* @param sqlKeyword SQL 关键词
|
||||
* @param val 条件值
|
||||
*/
|
||||
protected <X> Children addCondition(boolean condition, SFunction<X, ?> column, SqlKeyword sqlKeyword, Object val) {
|
||||
return doIt(condition, () -> columnToString(column), sqlKeyword, () -> formatSql("{0}", val));
|
||||
}
|
||||
|
||||
/**
|
||||
* 多重嵌套查询条件
|
||||
*
|
||||
* @param condition 查询条件值
|
||||
*/
|
||||
protected Children addNestedCondition(boolean condition, Consumer<Children> consumer) {
|
||||
if (condition) {
|
||||
final Children instance = instance();
|
||||
consumer.accept(instance);
|
||||
return doIt(true, APPLY, instance);
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 子类返回一个自己的新对象
|
||||
*/
|
||||
protected abstract Children instance();
|
||||
|
||||
/**
|
||||
* 格式化SQL
|
||||
*
|
||||
* @param sqlStr SQL语句部分
|
||||
* @param params 参数集
|
||||
* @return sql
|
||||
*/
|
||||
protected final String formatSql(String sqlStr, Object... params) {
|
||||
return formatSqlIfNeed(true, sqlStr, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据需要格式化SQL<br>
|
||||
* <br>
|
||||
* Format SQL for methods: EntityQ<T>.where/and/or...("name={0}", value);
|
||||
* ALL the {<b>i</b>} will be replaced with #{MPGENVAL<b>i</b>}<br>
|
||||
* <br>
|
||||
* ew.where("sample_name=<b>{0}</b>", "haha").and("sample_age ><b>{0}</b>
|
||||
* and sample_age<<b>{1}</b>", 18, 30) <b>TO</b>
|
||||
* sample_name=<b>#{MPGENVAL1}</b> and sample_age>#<b>{MPGENVAL2}</b> and
|
||||
* sample_age<<b>#{MPGENVAL3}</b><br>
|
||||
* </p>
|
||||
*
|
||||
* @param need 是否需要格式化
|
||||
* @param sqlStr SQL语句部分
|
||||
* @param params 参数集
|
||||
* @return sql
|
||||
*/
|
||||
protected final String formatSqlIfNeed(boolean need, String sqlStr, Object... params) {
|
||||
if (!need || StringUtils.isBlank(sqlStr)) {
|
||||
return null;
|
||||
}
|
||||
if (ArrayUtils.isNotEmpty(params)) {
|
||||
for (int i = 0; i < params.length; ++i) {
|
||||
String genParamName = Constants.WRAPPER_PARAM + paramNameSeq.incrementAndGet();
|
||||
sqlStr = sqlStr.replace(String.format("{%s}", i),
|
||||
String.format(Constants.WRAPPER_PARAM_FORMAT, Constants.WRAPPER, genParamName));
|
||||
paramNameValuePairs.put(genParamName, params[i]);
|
||||
}
|
||||
}
|
||||
return sqlStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取in表达式 包含括号
|
||||
*
|
||||
* @param value 集合
|
||||
*/
|
||||
private ISqlSegment inExpression(Collection<?> value) {
|
||||
return () -> value.stream().map(i -> formatSql("{0}", i))
|
||||
.collect(joining(StringPool.COMMA, StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET));
|
||||
}
|
||||
|
||||
/**
|
||||
* 必要的初始化
|
||||
*/
|
||||
protected void initNeed() {
|
||||
paramNameSeq = new AtomicInteger(0);
|
||||
paramNameValuePairs = new HashMap<>(16);
|
||||
expression = new MergeSegments();
|
||||
lastSql = SharedString.emptyString();
|
||||
sqlComment = SharedString.emptyString();
|
||||
sqlFirst = SharedString.emptyString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
entity = null;
|
||||
paramNameSeq.set(0);
|
||||
paramNameValuePairs.clear();
|
||||
expression.clear();
|
||||
lastSql.toEmpty();
|
||||
sqlComment.toEmpty();
|
||||
sqlFirst.toEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对sql片段进行组装
|
||||
*
|
||||
* @param condition 是否执行
|
||||
* @param sqlSegments sql片段数组
|
||||
* @return children
|
||||
*/
|
||||
protected Children doIt(boolean condition, ISqlSegment... sqlSegments) {
|
||||
if (condition) {
|
||||
expression.add(sqlSegments);
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlSegment() {
|
||||
return expression.getSqlSegment() + lastSql.getStringValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlComment() {
|
||||
if (StringUtils.isNotBlank(sqlComment.getStringValue())) {
|
||||
return "/*" + StringEscape.escapeRawString(sqlComment.getStringValue()) + "*/";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlFirst() {
|
||||
if (StringUtils.isNotBlank(sqlFirst.getStringValue())) {
|
||||
return StringEscape.escapeRawString(sqlFirst.getStringValue());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MergeSegments getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
public Map<String, Object> getParamNameValuePairs() {
|
||||
return paramNameValuePairs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 columnName
|
||||
*/
|
||||
protected <X> String columnToString(X column) {
|
||||
return (String) column;
|
||||
}
|
||||
|
||||
/**
|
||||
* 多字段转换为逗号 "," 分割字符串
|
||||
*
|
||||
* @param columns 多字段
|
||||
*/
|
||||
protected <X> String columnsToString(X... columns) {
|
||||
return Arrays.stream(columns).map(this::columnToString).collect(joining(StringPool.COMMA));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public Children clone() {
|
||||
return SerializationUtils.clone(typedThis);
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
package com.github.yulichang.common;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.SharedString;
|
||||
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 自定义连表sql
|
||||
* <p>
|
||||
* 不使用表别名:
|
||||
* <pre>
|
||||
* //注解
|
||||
* @Select("select user.*,user_address.tel from user left join user_address on user.id = user_address.user_id ${ew.customSqlSegment}")
|
||||
*
|
||||
* //或者xml
|
||||
* <select id="userLeftJoin" resultType="UserDTO">
|
||||
* select user.*, user_address.tel
|
||||
* from user left join user_address on user.id = user_address.user_id
|
||||
* ${ew.customSqlSegment}
|
||||
* </select>
|
||||
*
|
||||
* //mapper
|
||||
* UserDTO userLeftJoin(@Param(Constants.WRAPPER) Wrapper<UserDO> queryWrapper);
|
||||
*
|
||||
* wrapper使用方法:
|
||||
* UserDTO userDTO = userMapper.userLeftJoin(new JoinLambdaWrapper<UserDO>()
|
||||
* .eq(UserDO::getId, "1")
|
||||
* .eq(UserAddressDO::getUserId, "1"));
|
||||
*
|
||||
* 对应生成sql:
|
||||
* select user.*, user_address.tel
|
||||
* from user left join user_address on user.id = user_address.user_id
|
||||
* WHERE (
|
||||
* user.id = ?
|
||||
* AND user_address.user_id = ?)
|
||||
* </pre>
|
||||
* <p>
|
||||
* 使用别名:
|
||||
*
|
||||
* <pre>
|
||||
* //注解
|
||||
* @Select("select u.*,ua.tel from user u left join user_address ua on u.id = ua.user_id ${ew.customSqlSegment}")
|
||||
*
|
||||
* //或者xml
|
||||
* <select id="userLeftJoin" resultType="UserDTO">
|
||||
* select u.*, ua.tel
|
||||
* from user u left join user_address ua on u.id = ua.user_id
|
||||
* ${ew.customSqlSegment}
|
||||
* </select>
|
||||
*
|
||||
* //mapper
|
||||
* UserDTO userLeftJoin(@Param(Constants.WRAPPER) Wrapper<UserDO> queryWrapper);
|
||||
*
|
||||
* wrapper使用方法:
|
||||
* UserDTO userDTO = userMapper.userLeftJoin(new JoinLambdaWrapper<UserDO>()
|
||||
* .alias(UserDO.class, "u") //如果sql使用别名,需要再此定义别名
|
||||
* .alias(UserAddressDO.class, "ua") //如果sql使用别名,需要再此定义别名
|
||||
* .eq(UserDO::getId, "1")
|
||||
* .eq(UserAddressDO::getUserId, "1"));
|
||||
*
|
||||
* 对应生成sql:
|
||||
* select u.*, ua.tel
|
||||
* from user u left join user_address ua on u.id = ua.user_id
|
||||
* WHERE (
|
||||
* u.id = ?
|
||||
* AND ua.user_id = ?)
|
||||
* </pre>
|
||||
* <p>
|
||||
* 如需单独使用只需拷贝以下类
|
||||
* {@link com.github.yulichang.common.JoinLambdaWrapper}
|
||||
* {@link com.github.yulichang.common.JoinAbstractWrapper}
|
||||
* {@link com.github.yulichang.common.JoinAbstractLambdaWrapper}
|
||||
* {@link com.github.yulichang.wrapper.interfaces.Compare}
|
||||
* {@link com.github.yulichang.wrapper.interfaces.Func}
|
||||
* {@link com.github.yulichang.toolkit.LambdaUtils}
|
||||
* <p>
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.0.9
|
||||
*/
|
||||
public class JoinLambdaWrapper<T> extends JoinAbstractLambdaWrapper<T, JoinLambdaWrapper<T>> {
|
||||
|
||||
/**
|
||||
* 实体与别名对应关系
|
||||
*/
|
||||
public JoinLambdaWrapper<T> alias(Class<?> clazz, String alisa) {
|
||||
subTable.put(clazz, alisa);
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
|
||||
public JoinLambdaWrapper() {
|
||||
super.initNeed();
|
||||
}
|
||||
|
||||
/**
|
||||
* 不建议直接 new 该实例,使用 Wrappers.lambdaQuery(...)
|
||||
*/
|
||||
JoinLambdaWrapper(T entity, Class<T> entityClass, AtomicInteger paramNameSeq,
|
||||
Map<String, Object> 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.lastSql = lastSql;
|
||||
this.sqlComment = sqlComment;
|
||||
this.sqlFirst = sqlFirst;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JoinLambdaWrapper<T> instance() {
|
||||
return new JoinLambdaWrapper<>(getEntity(), getEntityClass(), paramNameSeq, paramNameValuePairs,
|
||||
new MergeSegments(), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
}
|
||||
}
|
||||
|
@ -1,136 +0,0 @@
|
||||
## 连表通用wrapper
|
||||
|
||||
[官方自定义sql](https://mp.baomidou.com/guide/wrapper.html#%E4%BD%BF%E7%94%A8-wrapper-%E8%87%AA%E5%AE%9A%E4%B9%89sql)
|
||||
|
||||
官方提供的自定义sql不支持表别名和多实体泛型,扩展能力有限,对此就行了优化
|
||||
|
||||
### 使用方法
|
||||
|
||||
#### 如需单独使用 请拷贝以下6个类
|
||||
|
||||
[com.github.yulichang.common.JoinLambdaWrapper](https://gitee.com/best_handsome/mybatis-plus-join/blob/master/src/main/java/com/github/yulichang/common/JoinLambdaWrapper.java)
|
||||
[com.github.yulichang.common.JoinAbstractWrapper](https://gitee.com/best_handsome/mybatis-plus-join/blob/master/src/main/java/com/github/yulichang/common/JoinAbstractLambdaWrapper.java)
|
||||
[com.github.yulichang.common.JoinAbstractLambdaWrapper](https://gitee.com/best_handsome/mybatis-plus-join/blob/master/src/main/java/com/github/yulichang/common/JoinAbstractLambdaWrapper.java)
|
||||
[com.github.yulichang.wrapper.interfaces.Compare](https://gitee.com/best_handsome/mybatis-plus-join/blob/master/src/main/java/com/github/yulichang/wrapper/interfaces/Compare.java)
|
||||
[com.github.yulichang.wrapper.interfaces.Func](https://gitee.com/best_handsome/mybatis-plus-join/blob/master/src/main/java/com/github/yulichang/wrapper/interfaces/Func.java)
|
||||
[com.github.yulichang.toolkit.LambdaUtils](https://gitee.com/best_handsome/mybatis-plus-join/blob/master/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java)
|
||||
|
||||
#### 不使用表别名
|
||||
|
||||
注解:
|
||||
|
||||
```java
|
||||
|
||||
@Mapper
|
||||
public interface UserMapper extends BaseMapper<UserDO> {
|
||||
|
||||
@Select("select user.*,user_address.tel from user left join user_address on user.id = user_address.user_id ${ew.customSqlSegment}")
|
||||
UserDTO userLeftJoin(@Param(Constants.WRAPPER) Wrapper<?> queryWrapper);
|
||||
}
|
||||
```
|
||||
|
||||
或者xml
|
||||
|
||||
```
|
||||
<select id="userLeftJoin" resultType="UserDTO">
|
||||
select
|
||||
user.*,
|
||||
user_address.tel
|
||||
from
|
||||
user
|
||||
left join user_address on user.id = user_address.user_id
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
```
|
||||
|
||||
使用wrapper:
|
||||
|
||||
```java
|
||||
class MpJoinTest {
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
UserDTO userDTO = userMapper.userLeftJoin(new JoinLambdaWrapper<>()
|
||||
.eq(UserDO::getId, "1")
|
||||
.eq(UserAddressDO::getUserId, "1"));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
对应sql:
|
||||
|
||||
```
|
||||
select
|
||||
user.*,
|
||||
user_address.tel
|
||||
from
|
||||
user
|
||||
left join user_address on user.id = user_address.user_id
|
||||
WHERE (
|
||||
user.id = ?
|
||||
AND user_address.user_id = ?)
|
||||
```
|
||||
|
||||
#### 使用表别名
|
||||
|
||||
注解:
|
||||
|
||||
```java
|
||||
|
||||
@Mapper
|
||||
public interface UserMapper extends BaseMapper<UserDO> {
|
||||
|
||||
@Select("select u.*,ua.tel from user u left join user_address ua on u.id = ua.user_id ${ew.customSqlSegment}")
|
||||
UserDTO userLeftJoin(@Param(Constants.WRAPPER) Wrapper<?> queryWrapper);
|
||||
}
|
||||
```
|
||||
|
||||
或者xml
|
||||
|
||||
```
|
||||
<select id="userLeftJoin" resultType="UserDTO">
|
||||
select
|
||||
u.*,
|
||||
ua.tel
|
||||
from
|
||||
user u
|
||||
left join user_address ua on u.id = ua.user_id
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
```
|
||||
|
||||
使用wrapper:
|
||||
|
||||
```java
|
||||
class MpJoinTest {
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
UserDTO userDTO = userMapper.userLeftJoin(new JoinLambdaWrapper<>()
|
||||
.alias(UserDO.class, "u") //如果使用别名需要再此声明别名与实体的对应关系
|
||||
.alias(UserAddressDO.class, "ua") //如果使用别名需要再此声明别名与实体的对应关系
|
||||
.eq(UserDO::getId, "1")
|
||||
.eq(UserAddressDO::getUserId, "1"));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
对应sql:
|
||||
|
||||
```
|
||||
select
|
||||
u.*,
|
||||
ua.tel
|
||||
from
|
||||
user u
|
||||
left join user_address ua on u.id = ua.user_id
|
||||
WHERE (
|
||||
u.id = ?
|
||||
AND ua.user_id = ?)
|
||||
```
|
||||
|
||||
QQ群:1022221898
|
@ -1,47 +0,0 @@
|
||||
package com.github.yulichang.common.support.alias;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
|
||||
/**
|
||||
* 字段添加别名
|
||||
* 使用方法:
|
||||
* <p>
|
||||
* select t.id,t.sex from table t ${ew.customSqlSegment("t")}
|
||||
* </p>
|
||||
* 对应sql
|
||||
* <p>
|
||||
* select t.id,t.sex from table t where t.id = ? and t.sex = ?
|
||||
* </p>
|
||||
* 注意:
|
||||
* 官方的自定义sql是ew.customSqlSegment,不带括号,会调用getCustomSqlSegment()方法
|
||||
* 带别名的是 ew.customSqlSegment("t") 带括号
|
||||
* 括号中的别名必须带双引号
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
public class AliasLambdaQueryWrapper<T> extends LambdaQueryWrapper<T> {
|
||||
/**
|
||||
* 字段别名
|
||||
*/
|
||||
private String alias;
|
||||
|
||||
/**
|
||||
* 重写字段序列化方法
|
||||
*/
|
||||
@Override
|
||||
protected String columnToString(SFunction<T, ?> column, boolean onlyColumn) {
|
||||
String as = super.columnToString(column, onlyColumn);
|
||||
return StringUtils.isBlank(alias) ? as : (alias + StringPool.DOT + as);
|
||||
}
|
||||
|
||||
/**
|
||||
* ew.customSqlSegment("t")
|
||||
*/
|
||||
public String customSqlSegment(String alias) {
|
||||
this.alias = alias;
|
||||
return super.getCustomSqlSegment();
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package com.github.yulichang.common.support.alias;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
|
||||
/**
|
||||
* 字段添加别名
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
public class AliasQueryWrapper<T> extends QueryWrapper<T> {
|
||||
/**
|
||||
* 字段别名
|
||||
*/
|
||||
private String alias;
|
||||
|
||||
public AliasQueryWrapper<T> setAlias(String alias) {
|
||||
this.alias = alias;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写字段序列化方法
|
||||
* 可以自定义过滤策略可以是空格或其他(以下方法是只为查询字段没有带点 . 的加别名,带点的则不会加)
|
||||
* setAlias("u")
|
||||
* <p>
|
||||
* .eq("id") --> u.id
|
||||
* .eq("ee.id") --> ee.id
|
||||
*/
|
||||
@Override
|
||||
protected String columnToString(String column) {
|
||||
if (column.lastIndexOf(StringPool.DOT) < 0) {
|
||||
return StringUtils.isBlank(alias) ? column : (alias + StringPool.DOT + column);
|
||||
} else {
|
||||
return column;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
## 别名wrapper用法
|
||||
|
||||
[官方自定义sql](https://mp.baomidou.com/guide/wrapper.html#%E4%BD%BF%E7%94%A8-wrapper-%E8%87%AA%E5%AE%9A%E4%B9%89sql)
|
||||
|
||||
官方提供的自定义sql不支持表别名和多实体泛型,扩展能力有限,对此就行了优化
|
||||
|
||||
原理:
|
||||
AliasQueryWrapper继承QueryWrapper
|
||||
AliasLambdaQueryWrapper继承LambdaQueryWrapper
|
||||
这两个类重写了父类字段序列化方法columnToString,添加别名
|
||||
|
||||
### 使用方法
|
||||
|
||||
根据你的需要拷贝以下类
|
||||
[com.github.yulichang.common.support.alias.AliasLambdaQueryWrapper](https://gitee.com/best_handsome/mybatis-plus-join/blob/master/src/main/java/com/github/yulichang/common/support/alias/AliasLambdaQueryWrapper.java)
|
||||
[com.github.yulichang.common.support.alias.AliasQueryWrapper](https://gitee.com/best_handsome/mybatis-plus-join/blob/master/src/main/java/com/github/yulichang/common/support/alias/AliasQueryWrapper.java)
|
||||
|
||||
#### AliasLambdaQueryWrapper
|
||||
|
||||
[感谢mybatis-plus PR 中的一位老哥的想法,以及实现](https://gitee.com/baomidou/mybatis-plus/pulls/137)
|
||||
|
||||
注解:
|
||||
|
||||
```java
|
||||
|
||||
@Mapper
|
||||
public interface UserMapper extends BaseMapper<UserDO> {
|
||||
|
||||
@Select("select u.*,ua.tel from user u left join user_address ua on u.id = ua.user_id ${ew.customSqlSegment(\"u\")}")
|
||||
UserDTO userLeftJoin(@Param(Constants.WRAPPER) Wrapper<?> queryWrapper);
|
||||
}
|
||||
```
|
||||
|
||||
或者xml
|
||||
|
||||
```
|
||||
<select id="userLeftJoin" resultType="UserDTO">
|
||||
select
|
||||
u.*,
|
||||
ua.tel
|
||||
from
|
||||
user u
|
||||
left join user_address ua on u.id = ua.user_id
|
||||
${ew.customSqlSegment("u")}
|
||||
</select>
|
||||
```
|
||||
|
||||
注意:
|
||||
官方的自定义sql是ew.customSqlSegment,不带括号,会调用getCustomSqlSegment方法
|
||||
带别名的是 ew.customSqlSegment("t") 带括号,调用的是AliasLambdaQueryWrapper#customSqlSegment(String alias)
|
||||
括号中的别名必须带双引号
|
||||
|
||||
使用wrapper:
|
||||
|
||||
```java
|
||||
class MpJoinTest {
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
UserDTO userDTO = userMapper.userLeftJoin(new AliasLambdaQueryWrapper<UserDO>()
|
||||
.eq(UserDO::getId, "1")
|
||||
.like(UserDO::getSex, "3"));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
对应sql:
|
||||
|
||||
```
|
||||
select
|
||||
u.*,
|
||||
ua.tel
|
||||
from user u
|
||||
left join user_address ua on u.id = ua.user_id
|
||||
WHERE (
|
||||
u.id = ?
|
||||
AND u.sex LIKE ?)
|
||||
```
|
||||
|
||||
#### AliasQueryWrapper
|
||||
|
||||
mybatis-plus原生的QueryWrapper也是可以实现别名的,但是没有统一的转换方法,开发时容易忽略
|
||||
|
||||
AliasQueryWrapper.setAlias("u").eq("id", 1);
|
||||
等效与
|
||||
QueryWrapper.eq("u.id", 1);
|
||||
|
||||
AliasQueryWrapper别名一次设置全局通用,不需要每个字段都加别名
|
||||
|
||||
说明:
|
||||
对于非主表字段查询也是支持的
|
||||
|
||||
```java
|
||||
class MpJoinTest {
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
UserDTO userDTO = userMapper.userLeftJoin(new AliasQueryWrapper<>()
|
||||
.setAlias("u")
|
||||
.eq("id", "1")
|
||||
.like("sex", "3")
|
||||
.eq("ua.tel", "10086") //如果查询字段中有点(.)则不会添加别名
|
||||
.like("ua.address", "北京"));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
对应sql:
|
||||
|
||||
```
|
||||
select
|
||||
u.*,
|
||||
ua.tel
|
||||
from user u
|
||||
left join user_address ua on u.id = ua.user_id
|
||||
WHERE (
|
||||
u.id = ?
|
||||
AND u.sex LIKE ?
|
||||
AND ua.tel = ?
|
||||
AND ua.address LIKE ?)
|
||||
```
|
||||
|
||||
注意:如果你喜欢骚操作,请使用原生QueryWrapper
|
||||
举例:
|
||||
|
||||
* .eq("(select sex from user where id = u.id)", "男")
|
||||
* .eq("count(u.id)", 1)
|
||||
|
||||
不建议在QueryWrapper中使用sql或函数
|
||||
除非你不考虑后续的维护和sql调优
|
||||
|
||||
QQ群:1022221898
|
@ -1,50 +0,0 @@
|
||||
package com.github.yulichang.common.support.func;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
|
||||
import org.apache.ibatis.reflection.property.PropertyNamer;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 使用表全名,不适用别名
|
||||
* UserDO::getId --> user.id
|
||||
* UserAddrDO::getTel --> user_addr.tel
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
public class F {
|
||||
|
||||
public static <T, R> String s(SFunction<T, R> sFunction) {
|
||||
Assert.notNull(sFunction, "function is null");
|
||||
return TableInfoHelper.getTableInfo(getEntityClass(sFunction)).getTableName()
|
||||
+ StringPool.DOT + getColumn(sFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
* 与S的getColumn一致,两个都用,保留一个就行了
|
||||
*/
|
||||
public static <T> String getColumn(SFunction<T, ?> fn) {
|
||||
SerializedLambda lambda = LambdaUtils.resolve(fn);
|
||||
String fieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName());
|
||||
try {
|
||||
TableField annotation = lambda.getImplClass().getDeclaredField(fieldName).getAnnotation(TableField.class);
|
||||
if (Objects.nonNull(annotation) && StringUtils.isNotBlank(annotation.value())) {
|
||||
return annotation.value();
|
||||
}
|
||||
} catch (NoSuchFieldException ignored) {
|
||||
}
|
||||
return StringUtils.camelToUnderline(fieldName);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> Class<T> getEntityClass(SFunction<T, ?> fn) {
|
||||
return (Class<T>) LambdaUtils.resolve(fn).getInstantiatedType();
|
||||
}
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
## 支持lambda的QueryWrapper
|
||||
[官方自定义sql](https://mp.baomidou.com/guide/wrapper.html#%E4%BD%BF%E7%94%A8-wrapper-%E8%87%AA%E5%AE%9A%E4%B9%89sql)
|
||||
让QueryWrapper也能使用lambda
|
||||
单表lambda请使用mybatis-plus提供的LambdaQueryWrapper
|
||||
本示例主要在连表的情况下使用!
|
||||
|
||||
### 使用方法
|
||||
|
||||
拷贝以下类即可
|
||||
[com.github.yulichang.common.support.func.F](https://gitee.com/best_handsome/mybatis-plus-join/blob/master/src/main/java/com/github/yulichang/common/support/func/F.java)
|
||||
[com.github.yulichang.common.support.func.S](https://gitee.com/best_handsome/mybatis-plus-join/blob/master/src/main/java/com/github/yulichang/common/support/func/S.java)
|
||||
|
||||
原理:
|
||||
F类以表名+列明的形式序列化 (@TableName与@TableField注解是有效的,会优先使用注解的值)
|
||||
|
||||
* F.s(UserDO::getId) --> user.id
|
||||
* F.s(UserAddrDO::getId) --> user_addr.id
|
||||
|
||||
S类以预定义表名+列明的形式序列化
|
||||
忽略表名,以预定义别名替代(@TableField注解是有效的,会优先使用注解的值)
|
||||
|
||||
* S.a(UserDO::getId) --> a.id
|
||||
* S.b(UserDO::getId) --> b.id
|
||||
* S.c(UserDO::getId) --> c.id
|
||||
* S.d(UserDO::getId) --> d.id
|
||||
* S.e(UserDO::getId) --> e.id
|
||||
* S.f(UserDO::getId) --> f.id
|
||||
|
||||
注解:
|
||||
|
||||
```java
|
||||
|
||||
@Mapper
|
||||
public interface UserMapper extends BaseMapper<UserDO> {
|
||||
/**
|
||||
* 使用 S
|
||||
*/
|
||||
@Select("select a.*,b.tel from user a " +
|
||||
"left join user_address b on a.id = b.user_id ${ew.customSqlSegment}")
|
||||
UserDTO userLeftJoin(@Param(Constants.WRAPPER) Wrapper<?> queryWrapper);
|
||||
|
||||
/**
|
||||
* 使用 F
|
||||
*/
|
||||
@Select("select user.*,user_address.tel from user " +
|
||||
"left join user_address on user.id = user_address.user_id ${ew.customSqlSegment}")
|
||||
UserDTO userLeftJoin(@Param(Constants.WRAPPER) Wrapper<?> queryWrapper);
|
||||
}
|
||||
```
|
||||
|
||||
或者xml
|
||||
|
||||
```
|
||||
<!-- 使用 S -->
|
||||
<select id="userLeftJoin" resultType="UserDTO">
|
||||
select
|
||||
a.*,
|
||||
b.tel
|
||||
from
|
||||
user a
|
||||
left join user_address b on a.id = b.user_id
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
<!-- 使用 F -->
|
||||
<select id="userLeftJoin" resultType="UserDTO">
|
||||
select
|
||||
user.*,
|
||||
user_address.tel
|
||||
from
|
||||
user
|
||||
left join user_address on user.id = user_address.user_id
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
```
|
||||
|
||||
使用wrapper:
|
||||
|
||||
```java
|
||||
class MpJoinTest {
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
/**
|
||||
* 使用S
|
||||
*/
|
||||
@Test
|
||||
void testS() {
|
||||
UserDTO dto = userMapper.userLeftJoin(new QueryWrapper<UserDO>()
|
||||
.eq(S.a(UserDO::getId), "1")//a.id
|
||||
.gt(S.a(UserDO::getSex), "3")//a.sex
|
||||
.eq(S.b(UserAddressDO::getTel), "10086")//b.tel
|
||||
.like(S.b(UserAddressDO::getAddress), "北京"));//b.address
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用F
|
||||
*/
|
||||
@Test
|
||||
void testF() {
|
||||
UserDTO dto = userMapper.userLeftJoin(new QueryWrapper<UserDO>()
|
||||
.eq(F.s(UserDO::getId), "1")//user.id
|
||||
.gt(F.s(UserDO::getSex), "3")//user.sex
|
||||
.eq(F.s(UserAddressDO::getTel), "10086")//user_address.tel
|
||||
.like(F.s(UserAddressDO::getAddress), "北京"));//user_address.address
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
对应sql:
|
||||
|
||||
```
|
||||
# 使用S
|
||||
select
|
||||
a.*,
|
||||
b.tel
|
||||
from user a
|
||||
left join user_address b on a.id = b.user_id
|
||||
WHERE (
|
||||
a.id = ?
|
||||
AND a.sex > ?
|
||||
AND b.tel = ?
|
||||
AND b.address LIKE ?)
|
||||
|
||||
# 使用F
|
||||
select
|
||||
user.*,
|
||||
user_address.tel
|
||||
from user
|
||||
left join user_address on user.id = user_address.user_id
|
||||
WHERE (
|
||||
user.id = ?
|
||||
AND user.sex > ?
|
||||
AND user_address.tel = ?
|
||||
AND user_address.address LIKE ?)
|
||||
```
|
||||
|
||||
QQ群:1022221898
|
@ -1,71 +0,0 @@
|
||||
package com.github.yulichang.common.support.func;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
|
||||
import org.apache.ibatis.reflection.property.PropertyNamer;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 预定义以下别名 可以自行设置别名
|
||||
* S.a(UserDO::getId) --> a.id
|
||||
* S.b(UserDO::getId) --> b.id
|
||||
* S.c(UserDO::getId) --> c.id
|
||||
* S.d(UserDO::getId) --> d.id
|
||||
* S.e(UserDO::getId) --> e.id
|
||||
* S.f(UserDO::getId) --> f.id
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
public class S {
|
||||
|
||||
public static <T, R> String a(SFunction<T, R> sFunction) {
|
||||
return getStrByAlias("a", sFunction);
|
||||
}
|
||||
|
||||
public static <T, R> String b(SFunction<T, R> sFunction) {
|
||||
return getStrByAlias("b", sFunction);
|
||||
}
|
||||
|
||||
public static <T, R> String c(SFunction<T, R> sFunction) {
|
||||
return getStrByAlias("c", sFunction);
|
||||
}
|
||||
|
||||
public static <T, R> String d(SFunction<T, R> sFunction) {
|
||||
return getStrByAlias("d", sFunction);
|
||||
}
|
||||
|
||||
public static <T, R> String e(SFunction<T, R> sFunction) {
|
||||
return getStrByAlias("e", sFunction);
|
||||
}
|
||||
|
||||
public static <T, R> String f(SFunction<T, R> sFunction) {
|
||||
return getStrByAlias("f", sFunction);
|
||||
}
|
||||
|
||||
private static <T, R> String getStrByAlias(String alias, SFunction<T, R> sFunction) {
|
||||
Assert.notNull(sFunction, "function is null");
|
||||
return alias + StringPool.DOT + getColumn(sFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
* 与F的getColumn一致,两个都用,保留一个就行了
|
||||
*/
|
||||
public static <T> String getColumn(SFunction<T, ?> fn) {
|
||||
SerializedLambda lambda = LambdaUtils.resolve(fn);
|
||||
String fieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName());
|
||||
try {
|
||||
TableField annotation = lambda.getImplClass().getDeclaredField(fieldName).getAnnotation(TableField.class);
|
||||
if (Objects.nonNull(annotation) && StringUtils.isNotBlank(annotation.value())) {
|
||||
return annotation.value();
|
||||
}
|
||||
} catch (NoSuchFieldException ignored) {
|
||||
}
|
||||
return StringUtils.camelToUnderline(fieldName);
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package com.github.yulichang.toolkit;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
|
||||
/**
|
||||
* 用于简化lambda中对象属性拷贝操作
|
||||
*
|
||||
* @author yulichang
|
||||
* @see org.springframework.beans.BeanUtils
|
||||
*/
|
||||
public class BeanUtils {
|
||||
|
||||
public static <T> T copyProperties(Object source, T target) throws BeansException {
|
||||
org.springframework.beans.BeanUtils.copyProperties(source, target);
|
||||
return target;
|
||||
}
|
||||
|
||||
public static <T> T copyProperties(Object source, T target, Class<?> editable) throws BeansException {
|
||||
org.springframework.beans.BeanUtils.copyProperties(source, target, editable);
|
||||
return target;
|
||||
}
|
||||
|
||||
public static <T> T copyProperties(Object source, T target, String... ignoreProperties) throws BeansException {
|
||||
org.springframework.beans.BeanUtils.copyProperties(source, target, ignoreProperties);
|
||||
return target;
|
||||
}
|
||||
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
package com.github.yulichang.toolkit;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
/**
|
||||
* 程序连表工具类
|
||||
* 通常用于将两个单表查询的结果合并
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
public class ListJoinUtils {
|
||||
|
||||
/**
|
||||
* example:
|
||||
* <pre>
|
||||
* leftJoin(left,right,(l,r) ->{
|
||||
* if(l.getId.equals(r.getLeftId())){
|
||||
* l.setXXX(r.getXXX());
|
||||
* ....
|
||||
* }
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param left 主表list
|
||||
* @param right 附表list
|
||||
* @param consumer 执行内容
|
||||
*/
|
||||
public static <L, R> void leftJoin(List<L> left, List<R> right, BiConsumer<L, R> consumer) {
|
||||
if (CollectionUtils.isNotEmpty(left) && CollectionUtils.isNotEmpty(right)) {
|
||||
for (L l : left) {
|
||||
if (Objects.nonNull(l)) {
|
||||
for (R r : right) {
|
||||
if (Objects.nonNull(r)) {
|
||||
consumer.accept(l, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* example:
|
||||
* <pre>
|
||||
* leftJoin(left, right,
|
||||
* (l, r) -> l.getId.equals(r.getLeftId()),
|
||||
* (l, r) -> {
|
||||
* l.setXXX(r.getXXX());
|
||||
* ....
|
||||
* }
|
||||
* );
|
||||
* </pre>
|
||||
*
|
||||
* @param left 主表list
|
||||
* @param right 附表list
|
||||
* @param predicate 条件
|
||||
* @param consumer 执行内容
|
||||
*/
|
||||
public static <L, R> void leftJoin(List<L> left, List<R> right, BiPredicate<L, R> predicate, BiConsumer<L, R> consumer) {
|
||||
if (CollectionUtils.isNotEmpty(left) && CollectionUtils.isNotEmpty(right)) {
|
||||
for (L l : left) {
|
||||
if (Objects.nonNull(l)) {
|
||||
for (R r : right) {
|
||||
if (Objects.nonNull(r)) {
|
||||
if (predicate.test(l, r)) {
|
||||
consumer.accept(l, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package com.github.yulichang.toolkit;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
*/
|
||||
public class StreamUtils {
|
||||
|
||||
public static <T, R> List<R> toList(List<T> list, Function<T, R> func) {
|
||||
if (CollectionUtils.isNotEmpty(list)) {
|
||||
return list.stream().map(func).collect(Collectors.toList());
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public static <T, R> Set<R> toSet(List<T> list, Function<T, R> func) {
|
||||
if (CollectionUtils.isNotEmpty(list)) {
|
||||
return list.stream().map(func).collect(Collectors.toSet());
|
||||
}
|
||||
return new HashSet<>();
|
||||
}
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
package com.github.yulichang.toolkit;
|
||||
|
||||
import com.github.yulichang.common.JoinLambdaWrapper;
|
||||
import com.github.yulichang.common.support.alias.AliasLambdaQueryWrapper;
|
||||
import com.github.yulichang.common.support.alias.AliasQueryWrapper;
|
||||
import com.github.yulichang.query.MPJLambdaQueryWrapper;
|
||||
import com.github.yulichang.query.MPJQueryWrapper;
|
||||
import com.github.yulichang.wrapper.MPJJoinLambdaQueryWrapper;
|
||||
@ -26,16 +23,4 @@ public class Wrappers {
|
||||
public static <T> MPJJoinLambdaQueryWrapper<T> lambdaJoinWrapper() {
|
||||
return new MPJJoinLambdaQueryWrapper<>();
|
||||
}
|
||||
|
||||
public static <T> JoinLambdaWrapper<T> commonJoin() {
|
||||
return new JoinLambdaWrapper<>();
|
||||
}
|
||||
|
||||
public static <T> AliasQueryWrapper<T> aliasQueryJoin() {
|
||||
return new AliasQueryWrapper<>();
|
||||
}
|
||||
|
||||
public static <T> AliasLambdaQueryWrapper<T> aliasLambdaJoin() {
|
||||
return new AliasLambdaQueryWrapper<>();
|
||||
}
|
||||
}
|
||||
|
3
src/main/resources/META-INF/spring.factories
Normal file
3
src/main/resources/META-INF/spring.factories
Normal file
@ -0,0 +1,3 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.github.yulichang.interceptor.MPJInterceptor,\
|
||||
com.github.yulichang.injector.MPJSqlInjector
|
Loading…
x
Reference in New Issue
Block a user