mirror of
https://gitee.com/best_handsome/mybatis-plus-join
synced 2025-07-11 00:02:22 +08:00
apt
This commit is contained in:
parent
de3504ed5e
commit
9d37dd4d7c
@ -0,0 +1,37 @@
|
|||||||
|
package com.github.yulichang.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
public @interface Table {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成类的类名前缀
|
||||||
|
*/
|
||||||
|
String prefix() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成类的类名后缀
|
||||||
|
*/
|
||||||
|
String suffix() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* format 优先级低,如果配置了prefix或suffix则不会生效
|
||||||
|
*/
|
||||||
|
String format() default "%sCol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成类的包名
|
||||||
|
*/
|
||||||
|
String packageName() default "apt";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tables中的字段名 默认大写的类名
|
||||||
|
*/
|
||||||
|
String tablesName() default "%S";
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.github.yulichang.apt;
|
||||||
|
|
||||||
|
public interface BaseColumn<T> {
|
||||||
|
|
||||||
|
Class<T> getColumnClass();
|
||||||
|
|
||||||
|
String getAlias();
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.github.yulichang.apt;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Column {
|
||||||
|
|
||||||
|
private BaseColumn<?> root;
|
||||||
|
|
||||||
|
private Class<?> clazz;
|
||||||
|
|
||||||
|
private String property;
|
||||||
|
|
||||||
|
private Supplier<String> alias;
|
||||||
|
}
|
@ -95,7 +95,7 @@ public class MPJInterceptor implements Interceptor {
|
|||||||
wrapper.setEntityClass((Class<E>) MPJTableMapperHelper.getEntity(getMapper(ms.getId(), ms.getResource())));
|
wrapper.setEntityClass((Class<E>) MPJTableMapperHelper.getEntity(getMapper(ms.getId(), ms.getResource())));
|
||||||
}
|
}
|
||||||
if (wrapper.getSelectColumns().isEmpty() && wrapper.getEntityClass() != null) {
|
if (wrapper.getSelectColumns().isEmpty() && wrapper.getEntityClass() != null) {
|
||||||
wrapper.selectAll(wrapper.getEntityClass());
|
wrapper.selectAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return buildMappedStatement(ms, resultType, ew);
|
return buildMappedStatement(ms, resultType, ew);
|
||||||
@ -181,9 +181,8 @@ public class MPJInterceptor implements Interceptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (wrapper.isResultMap()) {
|
if (wrapper.isResultMap()) {
|
||||||
for (Object o : wrapper.getResultMapMybatisLabel()) {
|
for (Label<?> o : wrapper.getResultMapMybatisLabel()) {
|
||||||
Label<?> label = (Label<?>) o;
|
resultMappings.add(buildResult(ms, o, columnSet, columnList));
|
||||||
resultMappings.add(buildResult(ms, label, columnSet, columnList));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.add(new ResultMap.Builder(ms.getConfiguration(), id, resultType, resultMappings).build());
|
result.add(new ResultMap.Builder(ms.getConfiguration(), id, resultType, resultMappings).build());
|
||||||
@ -228,10 +227,10 @@ public class MPJInterceptor implements Interceptor {
|
|||||||
String index = r.getIndex();
|
String index = r.getIndex();
|
||||||
if (columnSet.contains(columnName)) {
|
if (columnSet.contains(columnName)) {
|
||||||
columnName = getColumn(columnSet, columnName, 0);
|
columnName = getColumn(columnSet, columnName, 0);
|
||||||
label = new SelectLabel(r.getSelectNormal(), null, mybatisLabel.getOfType(), columnName, StringUtils.isNotBlank(index), index);
|
label = new SelectLabel(r.getSelectNormal(), null, mybatisLabel.getOfType(), columnName, StringUtils.isNotBlank(index), index, r.getBaseColumn());
|
||||||
} else {
|
} else {
|
||||||
columnSet.add(columnName);
|
columnSet.add(columnName);
|
||||||
label = new SelectLabel(r.getSelectNormal(), null, mybatisLabel.getOfType(), StringUtils.isNotBlank(index), index);
|
label = new SelectLabel(r.getSelectNormal(), null, mybatisLabel.getOfType(), StringUtils.isNotBlank(index), index, r.getBaseColumn());
|
||||||
}
|
}
|
||||||
columnList.add(label);
|
columnList.add(label);
|
||||||
ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), r.getProperty(), columnName, r.getJavaType());
|
ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), r.getProperty(), columnName, r.getJavaType());
|
||||||
|
@ -188,8 +188,8 @@ public class KtLambdaWrapper<T> extends KtAbstractLambdaWrapper<T, KtLambdaWrapp
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KtLambdaWrapper<T> selectAll(Class<?> clazz) {
|
public KtLambdaWrapper<T> selectAll() {
|
||||||
return Query.super.selectAll(clazz);
|
return Query.super.selectAll(getEntityClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,7 +16,9 @@ import java.util.Arrays;
|
|||||||
public class FuncArgs {
|
public class FuncArgs {
|
||||||
|
|
||||||
public SelectFunc.Arg[] accept(KProperty<?>... kProperty) {
|
public SelectFunc.Arg[] accept(KProperty<?>... kProperty) {
|
||||||
return Arrays.stream(kProperty).map(i -> new SelectFunc.Arg(KtUtils.ref(i), i.getName(), false, null, i)).toArray(SelectFunc.Arg[]::new);
|
return Arrays.stream(kProperty).map(i ->
|
||||||
|
new SelectFunc.Arg(KtUtils.ref(i), i.getName(), false, null, i))
|
||||||
|
.toArray(SelectFunc.Arg[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,149 @@
|
|||||||
|
package com.github.yulichang.toolkit;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||||
|
import com.github.yulichang.adapter.AdapterHelper;
|
||||||
|
import com.github.yulichang.toolkit.sql.SqlScriptUtils;
|
||||||
|
import com.github.yulichang.wrapper.apt.AptQueryWrapper;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.4.5
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
|
public class AptWrapperUtils {
|
||||||
|
|
||||||
|
public static <T> String buildSubSqlByWrapper(Class<T> clazz, AptQueryWrapper<T> wrapper, String alias) {
|
||||||
|
TableInfo tableInfo = TableHelper.getAssert(clazz);
|
||||||
|
String first = Optional.ofNullable(wrapper.getSqlFirst()).orElse(StringPool.EMPTY);
|
||||||
|
boolean hasWhere = false;
|
||||||
|
String entityWhere = getEntitySql(tableInfo, wrapper);
|
||||||
|
if (StringUtils.isNotBlank(entityWhere)) {
|
||||||
|
hasWhere = true;
|
||||||
|
}
|
||||||
|
String mainLogic = mainLogic(hasWhere, clazz, wrapper);
|
||||||
|
if (StringUtils.isNotBlank(mainLogic)) {
|
||||||
|
hasWhere = true;
|
||||||
|
}
|
||||||
|
String subLogic = subLogic(hasWhere, wrapper);
|
||||||
|
if (StringUtils.isNotBlank(subLogic)) {
|
||||||
|
hasWhere = true;
|
||||||
|
}
|
||||||
|
String sqlSegment = (wrapper.getSqlSegment() != null && StringUtils.isNotBlank(wrapper.getSqlSegment())) ?
|
||||||
|
((wrapper.isEmptyOfNormal() ? StringPool.EMPTY : (hasWhere ? " AND " : " WHERE ")) + wrapper.getSqlSegment()) : StringPool.EMPTY;
|
||||||
|
|
||||||
|
String sqlComment = Optional.ofNullable(wrapper.getSqlComment()).orElse(StringPool.EMPTY);
|
||||||
|
return String.format(" (%s SELECT %s FROM %s %s %s %s %s %s %s) AS %s ",
|
||||||
|
first,
|
||||||
|
wrapper.getSqlSelect(),
|
||||||
|
wrapper.getTableName(tableInfo.getTableName()),
|
||||||
|
wrapper.getAlias(),
|
||||||
|
wrapper.getFrom(),
|
||||||
|
mainLogic,
|
||||||
|
subLogic,
|
||||||
|
sqlSegment,
|
||||||
|
sqlComment,
|
||||||
|
alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String buildUnionSqlByWrapper(Class<?> clazz, AptQueryWrapper<?> wrapper) {
|
||||||
|
TableInfo tableInfo = TableHelper.getAssert(clazz);
|
||||||
|
String first = Optional.ofNullable(wrapper.getSqlFirst()).orElse(StringPool.EMPTY);
|
||||||
|
boolean hasWhere = false;
|
||||||
|
String entityWhere = getEntitySql(tableInfo, wrapper);
|
||||||
|
if (StringUtils.isNotBlank(entityWhere)) {
|
||||||
|
hasWhere = true;
|
||||||
|
}
|
||||||
|
String mainLogic = mainLogic(hasWhere, clazz, wrapper);
|
||||||
|
if (StringUtils.isNotBlank(mainLogic)) {
|
||||||
|
hasWhere = true;
|
||||||
|
}
|
||||||
|
String subLogic = subLogic(hasWhere, wrapper);
|
||||||
|
if (StringUtils.isNotBlank(subLogic)) {
|
||||||
|
hasWhere = true;
|
||||||
|
}
|
||||||
|
String sqlSegment = (wrapper.getSqlSegment() != null && StringUtils.isNotBlank(wrapper.getSqlSegment())) ?
|
||||||
|
((wrapper.isEmptyOfNormal() ? StringPool.EMPTY : (hasWhere ? " AND " : " WHERE ")) + wrapper.getSqlSegment()) : StringPool.EMPTY;
|
||||||
|
|
||||||
|
String sqlComment = Optional.ofNullable(wrapper.getSqlComment()).orElse(StringPool.EMPTY);
|
||||||
|
return String.format(" %s SELECT %s FROM %s %s %s %s %s %s %s ",
|
||||||
|
first,
|
||||||
|
wrapper.getSqlSelect(),
|
||||||
|
wrapper.getTableName(tableInfo.getTableName()),
|
||||||
|
wrapper.getAlias(),
|
||||||
|
wrapper.getFrom(),
|
||||||
|
mainLogic,
|
||||||
|
subLogic,
|
||||||
|
sqlSegment,
|
||||||
|
sqlComment);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> String formatParam(AptQueryWrapper<T> wrapper, Object param) {
|
||||||
|
final String genParamName = Constants.WRAPPER_PARAM + wrapper.getParamNameSeq().incrementAndGet();
|
||||||
|
final String paramStr = wrapper.getParamAlias() + ".paramNameValuePairs." + genParamName;
|
||||||
|
wrapper.getParamNameValuePairs().put(genParamName, param);
|
||||||
|
return SqlScriptUtils.safeParam(paramStr, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getEntitySql(TableInfo tableInfo, AptQueryWrapper<?> wrapper) {
|
||||||
|
Object obj = wrapper.getEntity();
|
||||||
|
if (Objects.isNull(obj)) {
|
||||||
|
return StringPool.EMPTY;
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder(StringPool.EMPTY);
|
||||||
|
for (TableFieldInfo fieldInfo : tableInfo.getFieldList()) {
|
||||||
|
if (AdapterHelper.getAdapter().mpjHasLogic(tableInfo) && fieldInfo.isLogicDelete()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Object val;
|
||||||
|
try {
|
||||||
|
val = fieldInfo.getField().get(obj);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
if (Objects.isNull(val)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String s = wrapper.getAptIndex().get(wrapper.getBaseColumn());
|
||||||
|
sb.append(" AND ").append(s == null ? wrapper.getAlias() : s).append(Constants.DOT)
|
||||||
|
.append(fieldInfo.getColumn()).append(Constants.EQUALS).append(formatParam(wrapper, val));
|
||||||
|
}
|
||||||
|
//条件不为空 加上 where
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
sb.delete(0, 4);
|
||||||
|
sb.insert(0, " WHERE ");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String mainLogic(boolean hasWhere, Class<?> clazz, AptQueryWrapper<?> wrapper) {
|
||||||
|
if (!wrapper.getLogicSql()) {
|
||||||
|
return StringPool.EMPTY;
|
||||||
|
}
|
||||||
|
String info = LogicInfoUtils.getLogicInfo(null, clazz, true, wrapper.getAlias());
|
||||||
|
if (StringUtils.isNotBlank(info)) {
|
||||||
|
if (hasWhere) {
|
||||||
|
return " AND " + info;
|
||||||
|
}
|
||||||
|
return " WHERE " + info.substring(4);
|
||||||
|
}
|
||||||
|
return StringPool.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String subLogic(boolean hasWhere, AptQueryWrapper<?> wrapper) {
|
||||||
|
String sql = wrapper.getSubLogicSql();
|
||||||
|
if (StringUtils.isNotBlank(sql)) {
|
||||||
|
if (hasWhere) {
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
return " WHERE " + sql.substring(4);
|
||||||
|
}
|
||||||
|
return StringPool.EMPTY;
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
package com.github.yulichang.toolkit;
|
package com.github.yulichang.toolkit;
|
||||||
|
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
import com.github.yulichang.query.MPJQueryWrapper;
|
import com.github.yulichang.query.MPJQueryWrapper;
|
||||||
import com.github.yulichang.wrapper.DeleteJoinWrapper;
|
import com.github.yulichang.wrapper.DeleteJoinWrapper;
|
||||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||||
import com.github.yulichang.wrapper.UpdateJoinWrapper;
|
import com.github.yulichang.wrapper.UpdateJoinWrapper;
|
||||||
|
import com.github.yulichang.wrapper.apt.AptQueryWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yulichang
|
* @author yulichang
|
||||||
@ -102,4 +104,18 @@ public class JoinWrappers {
|
|||||||
public static <T> UpdateJoinWrapper<T> update(String alias, Class<T> clazz) {
|
public static <T> UpdateJoinWrapper<T> update(String alias, Class<T> clazz) {
|
||||||
return new UpdateJoinWrapper<>(clazz, alias);
|
return new UpdateJoinWrapper<>(clazz, alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JoinWrappers.apt(User.class)
|
||||||
|
*/
|
||||||
|
public static <T> AptQueryWrapper<T> apt(BaseColumn<T> baseColumn) {
|
||||||
|
return new AptQueryWrapper<>(baseColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JoinWrappers.apt("t", User.class)
|
||||||
|
*/
|
||||||
|
public static <T> AptQueryWrapper<T> apt(BaseColumn<T> baseColumn, T entity) {
|
||||||
|
return new AptQueryWrapper<>(baseColumn, entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,11 @@ public class LogicInfoUtils implements Constants {
|
|||||||
return absent.computeIfAbsent(hasAlias ? alias : (alias + tableIndex), key -> getLogicStr(key, clazz, true, false));
|
return absent.computeIfAbsent(hasAlias ? alias : (alias + tableIndex), key -> getLogicStr(key, clazz, true, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getLogicInfoApt(Class<?> clazz, String alias) {
|
||||||
|
Map<String, String> absent = LOGIC_CACHE.computeIfAbsent(clazz, k -> new ConcurrentHashMap<>());
|
||||||
|
return absent.computeIfAbsent(alias, key -> getLogicStr(key, clazz, true, false));
|
||||||
|
}
|
||||||
|
|
||||||
public static String getLogicInfoNoAnd(Integer tableIndex, Class<?> clazz, boolean hasAlias, String alias) {
|
public static String getLogicInfoNoAnd(Integer tableIndex, Class<?> clazz, boolean hasAlias, String alias) {
|
||||||
Map<String, String> absent = LOGIC_CACHE_NO_AND.computeIfAbsent(clazz, k -> new ConcurrentHashMap<>());
|
Map<String, String> absent = LOGIC_CACHE_NO_AND.computeIfAbsent(clazz, k -> new ConcurrentHashMap<>());
|
||||||
return absent.computeIfAbsent(hasAlias ? alias : (alias + tableIndex), key -> getLogicStr(key, clazz, false, false));
|
return absent.computeIfAbsent(hasAlias ? alias : (alias + tableIndex), key -> getLogicStr(key, clazz, false, false));
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package com.github.yulichang.toolkit;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class TableMap<K, V> {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final K root;
|
||||||
|
@Getter
|
||||||
|
private final String rootAlias;
|
||||||
|
|
||||||
|
private final Map<K, V> map = new HashMap<>();
|
||||||
|
|
||||||
|
private final List<K> list = new ArrayList<>();
|
||||||
|
|
||||||
|
public TableMap(K root, String rootAlias) {
|
||||||
|
this.root = root;
|
||||||
|
this.rootAlias = rootAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public V put(K key, V value) {
|
||||||
|
V v = this.map.put(key, value);
|
||||||
|
if (null == v) {
|
||||||
|
this.list.add(key);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public V get(K key) {
|
||||||
|
return this.map.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<K> keyList() {
|
||||||
|
return this.list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return this.map.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
this.map.clear();
|
||||||
|
this.list.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -261,33 +261,6 @@ public class MPJLambdaWrapper<T> extends JoinAbstractLambdaWrapper<T, MPJLambdaW
|
|||||||
return typedThis;
|
return typedThis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* union
|
|
||||||
* <p>
|
|
||||||
* 推荐使用 union(Class<U> clazz, ConsumerConsumer<MPJLambdaWrapper<U>> consumer)
|
|
||||||
* <p>
|
|
||||||
* 例: wrapper.union(UserDO.class, union -> union.selectAll(UserDO.class))
|
|
||||||
*
|
|
||||||
* @see #union(Class, Consumer)
|
|
||||||
* @deprecated union 不支持子查询
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@SuppressWarnings({"UnusedReturnValue", "DeprecatedIsStillUsed"})
|
|
||||||
public final MPJLambdaWrapper<T> union(MPJLambdaWrapper<?>... wrappers) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (MPJLambdaWrapper<?> wrapper : wrappers) {
|
|
||||||
addCustomWrapper(wrapper);
|
|
||||||
Class<?> entityClass = wrapper.getEntityClass();
|
|
||||||
Assert.notNull(entityClass, "请使用 new MPJLambdaWrapper(主表.class) 或 JoinWrappers.lambda(主表.class) 构造方法");
|
|
||||||
sb.append(" UNION ").append(WrapperUtils.buildUnionSqlByWrapper(entityClass, wrapper));
|
|
||||||
}
|
|
||||||
if (Objects.isNull(unionSql)) {
|
|
||||||
unionSql = SharedString.emptyString();
|
|
||||||
}
|
|
||||||
unionSql.setStringValue(unionSql.getStringValue() + sb);
|
|
||||||
return typedThis;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* union
|
* union
|
||||||
* <p>
|
* <p>
|
||||||
@ -310,32 +283,6 @@ public class MPJLambdaWrapper<T> extends JoinAbstractLambdaWrapper<T, MPJLambdaW
|
|||||||
return typedThis;
|
return typedThis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* union
|
|
||||||
* <p>
|
|
||||||
* 推荐使用 unionAll(Class<U> clazz, Consumer<MPJLambdaWrapper<U>> consumer)
|
|
||||||
* <p>
|
|
||||||
* 例: wrapper.unionAll(UserDO.class, union -> union.selectAll(UserDO.class))
|
|
||||||
*
|
|
||||||
* @see #unionAll(Class, Consumer)
|
|
||||||
* @deprecated union 不支持子查询
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@SuppressWarnings("DeprecatedIsStillUsed")
|
|
||||||
public MPJLambdaWrapper<T> unionAll(MPJLambdaWrapper<?>... wrappers) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (MPJLambdaWrapper<?> wrapper : wrappers) {
|
|
||||||
addCustomWrapper(wrapper);
|
|
||||||
Class<?> entityClass = wrapper.getEntityClass();
|
|
||||||
Assert.notNull(entityClass, "请使用 new MPJLambdaWrapper(主表.class) 或 JoinWrappers.lambda(主表.class) 构造方法");
|
|
||||||
sb.append(" UNION ALL ").append(WrapperUtils.buildUnionSqlByWrapper(entityClass, wrapper));
|
|
||||||
}
|
|
||||||
if (Objects.isNull(unionSql)) {
|
|
||||||
unionSql = SharedString.emptyString();
|
|
||||||
}
|
|
||||||
unionSql.setStringValue(unionSql.getStringValue() + sb);
|
|
||||||
return typedThis;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* union
|
* union
|
||||||
@ -386,15 +333,7 @@ public class MPJLambdaWrapper<T> extends JoinAbstractLambdaWrapper<T, MPJLambdaW
|
|||||||
if (i.isHasTableAlias()) {
|
if (i.isHasTableAlias()) {
|
||||||
prefix = i.getTableAlias();
|
prefix = i.getTableAlias();
|
||||||
} else {
|
} else {
|
||||||
if (i.isLabel()) {
|
prefix = tableList.getPrefix(i.getIndex(), i.getClazz(), i.isLabel());
|
||||||
if (i.isHasTableAlias()) {
|
|
||||||
prefix = i.getTableAlias();
|
|
||||||
} else {
|
|
||||||
prefix = tableList.getPrefix(i.getIndex(), i.getClazz(), true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
prefix = tableList.getPrefix(i.getIndex(), i.getClazz(), false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
String str = prefix + StringPool.DOT + i.getColumn();
|
String str = prefix + StringPool.DOT + i.getColumn();
|
||||||
if (i.isFunc()) {
|
if (i.isFunc()) {
|
||||||
|
@ -0,0 +1,432 @@
|
|||||||
|
package com.github.yulichang.wrapper.apt;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.OrderBy;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.SharedString;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||||
|
import com.github.yulichang.adapter.AdapterHelper;
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
import com.github.yulichang.config.ConfigProperties;
|
||||||
|
import com.github.yulichang.config.enums.LogicDelTypeEnum;
|
||||||
|
import com.github.yulichang.toolkit.Constant;
|
||||||
|
import com.github.yulichang.toolkit.LogicInfoUtils;
|
||||||
|
import com.github.yulichang.toolkit.TableHelper;
|
||||||
|
import com.github.yulichang.toolkit.TableMap;
|
||||||
|
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||||
|
import com.github.yulichang.wrapper.apt.interfaces.QueryJoin;
|
||||||
|
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||||
|
import com.github.yulichang.wrapper.segments.SelectCache;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.baomidou.mybatisplus.core.enums.WrapperKeyword.APPLY;
|
||||||
|
import static java.util.stream.Collectors.joining;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参考 {@link com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper}
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"DuplicatedCode", "unused"})
|
||||||
|
public abstract class AptAbstractWrapper<T, Children extends AptAbstractWrapper<T, Children>>
|
||||||
|
extends JoinAbstractWrapper<T, Children> implements QueryJoin<Children, T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主表别名
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
protected String alias = ConfigProperties.tableAlias;
|
||||||
|
/**
|
||||||
|
* 副表别名
|
||||||
|
*/
|
||||||
|
protected String subTableAlias = ConfigProperties.tableAlias;
|
||||||
|
/**
|
||||||
|
* 是否构建是否存在一对多
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
protected boolean resultMap = false;
|
||||||
|
/**
|
||||||
|
* 表序号
|
||||||
|
*/
|
||||||
|
protected int tableIndex = 1;
|
||||||
|
|
||||||
|
protected boolean isMain = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主表 表名处理方法
|
||||||
|
*/
|
||||||
|
protected boolean dynamicTableName = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主表 表名处理方法
|
||||||
|
*/
|
||||||
|
protected Function<String, String> tableFunc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 逻辑删除位置
|
||||||
|
*/
|
||||||
|
protected LogicDelTypeEnum logicDelType = ConfigProperties.logicDelType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询表
|
||||||
|
*/
|
||||||
|
protected final SharedString from = new SharedString();
|
||||||
|
/**
|
||||||
|
* 是否有表别名
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
protected boolean hasAlias;
|
||||||
|
/**
|
||||||
|
* 连表关键字 on 条件 func 使用
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
protected String keyWord;
|
||||||
|
/**
|
||||||
|
* 副表逻辑删除开关
|
||||||
|
*/
|
||||||
|
protected boolean subLogicSql = ConfigProperties.subTableLogic;
|
||||||
|
/**
|
||||||
|
* 主表逻辑删除开关
|
||||||
|
*/
|
||||||
|
protected boolean logicSql = true;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
protected BaseColumn<T> baseColumn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apt别名对应
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
protected TableMap<BaseColumn<?>, String> aptIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造方法
|
||||||
|
*/
|
||||||
|
protected AptAbstractWrapper(BaseColumn<T> baseColumn) {
|
||||||
|
this.alias = StringUtils.isNotBlank(baseColumn.getAlias()) ? baseColumn.getAlias() : this.alias;
|
||||||
|
setEntityClass(baseColumn.getColumnClass());
|
||||||
|
this.baseColumn = baseColumn;
|
||||||
|
initNeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造方法
|
||||||
|
*
|
||||||
|
* @param entity 主表实体类
|
||||||
|
*/
|
||||||
|
protected AptAbstractWrapper(BaseColumn<T> baseColumn, T entity) {
|
||||||
|
this.alias = StringUtils.isNotBlank(baseColumn.getAlias()) ? baseColumn.getAlias() : this.alias;
|
||||||
|
setEntity(entity);
|
||||||
|
this.baseColumn = baseColumn;
|
||||||
|
initNeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置表别名
|
||||||
|
* 设置表别名注意sql注入问题
|
||||||
|
*
|
||||||
|
* @return 自定义表别名
|
||||||
|
*/
|
||||||
|
public Children setTableName(Function<String, String> tableFunc) {
|
||||||
|
if (isMain) {
|
||||||
|
if (tableFunc != null) {
|
||||||
|
this.dynamicTableName = true;
|
||||||
|
this.tableFunc = tableFunc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.tableName = tableFunc.apply(this.tableName);
|
||||||
|
}
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTableName(String tableName) {
|
||||||
|
if (isMain) {
|
||||||
|
if (dynamicTableName) {
|
||||||
|
return tableFunc.apply(tableName);
|
||||||
|
}
|
||||||
|
return tableName;
|
||||||
|
}
|
||||||
|
return super.getTableName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getTableNameEnc(String tableName) {
|
||||||
|
Class<T> entityClass = getEntityClass();
|
||||||
|
if (entityClass != null) {
|
||||||
|
TableInfo tableInfo = TableHelper.get(entityClass);
|
||||||
|
if (tableInfo != null) {
|
||||||
|
if (dynamicTableName) {
|
||||||
|
return tableFunc.apply(tableInfo.getTableName());
|
||||||
|
}
|
||||||
|
return tableInfo.getTableName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String decode;
|
||||||
|
try {
|
||||||
|
decode = URLDecoder.decode(tableName, StandardCharsets.UTF_8.name());
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
if (dynamicTableName) {
|
||||||
|
return tableFunc.apply(decode);
|
||||||
|
}
|
||||||
|
return decode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected String getPrefix(BaseColumn<?> baseColumn) {
|
||||||
|
if (Objects.nonNull(baseColumn.getAlias())) {
|
||||||
|
return baseColumn.getAlias();
|
||||||
|
}
|
||||||
|
if (aptIndex.getRoot() == baseColumn) {
|
||||||
|
return aptIndex.getRootAlias();
|
||||||
|
}
|
||||||
|
String pf = aptIndex.get(baseColumn);
|
||||||
|
Assert.notEmpty(pf, "table not find %s", baseColumn.getColumnClass().getName());
|
||||||
|
return pf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String columnsToString(Column... columns) {
|
||||||
|
return Arrays.stream(columns).map(this::columnToString)
|
||||||
|
.collect(joining(StringPool.COMMA));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String columnToString(Column column) {
|
||||||
|
String pf = column.getAlias().get();
|
||||||
|
if (Objects.nonNull(pf)) {
|
||||||
|
return pf + StringPool.DOT + getCache(column).getColumn();
|
||||||
|
}
|
||||||
|
return getPrefix(column.getRoot()) + StringPool.DOT + getCache(column).getColumn();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SelectCache getCache(Column fn) {
|
||||||
|
Map<String, SelectCache> cacheMap = ColumnCache.getMapField(fn.getClazz());
|
||||||
|
return cacheMap.get(fn.getProperty());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭副表逻辑删除
|
||||||
|
* <p>
|
||||||
|
* 副表逻辑删除默认在where语句中
|
||||||
|
* 但有时候需要让它出现在on语句中, 这两种写法区别还是很大的
|
||||||
|
* 所以可以关闭副表逻辑删除, 通过on语句多条件, 自己实现on语句的逻辑删除
|
||||||
|
*/
|
||||||
|
public Children disableSubLogicDel() {
|
||||||
|
this.subLogicSql = false;
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Children enableSubLogicDel() {
|
||||||
|
this.subLogicSql = true;
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭主表逻辑删除
|
||||||
|
*/
|
||||||
|
public Children disableLogicDel() {
|
||||||
|
this.logicSql = false;
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Children enableLogicDel() {
|
||||||
|
this.logicSql = true;
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 副表部分逻辑删除支持
|
||||||
|
*/
|
||||||
|
public String getSubLogicSql() {
|
||||||
|
if (subLogicSql && logicDelType == LogicDelTypeEnum.WHERE) {
|
||||||
|
if (aptIndex.isEmpty()) {
|
||||||
|
return StringPool.EMPTY;
|
||||||
|
}
|
||||||
|
return aptIndex.keyList().stream().map(key -> LogicInfoUtils.getLogicInfoApt(key.getColumnClass(), getPrefix(key)))
|
||||||
|
.collect(Collectors.joining(StringPool.SPACE));
|
||||||
|
}
|
||||||
|
return StringPool.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主表部分逻辑删除支持
|
||||||
|
*/
|
||||||
|
public boolean getLogicSql() {
|
||||||
|
return this.logicSql;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调整逻辑删除位置为ON语句
|
||||||
|
*/
|
||||||
|
public Children logicDelToOn() {
|
||||||
|
this.logicDelType = LogicDelTypeEnum.ON;
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调整逻辑删除位置为WHERE语句
|
||||||
|
*/
|
||||||
|
public Children logicDelToWhere() {
|
||||||
|
this.logicDelType = LogicDelTypeEnum.WHERE;
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取连表部分语句
|
||||||
|
*/
|
||||||
|
public String getFrom() {
|
||||||
|
if (StringUtils.isBlank(from.getStringValue())) {
|
||||||
|
StringBuilder value = new StringBuilder();
|
||||||
|
for (Children wrapper : onWrappers) {
|
||||||
|
if (StringUtils.isBlank(wrapper.from.getStringValue())) {
|
||||||
|
if (this.subLogicSql && this.logicDelType == LogicDelTypeEnum.ON) {
|
||||||
|
TableInfo tableInfo = TableHelper.getAssert(wrapper.getJoinClass());
|
||||||
|
if (AdapterHelper.getAdapter().mpjHasLogic(tableInfo)) {
|
||||||
|
wrapper.appendSqlSegments(APPLY, () -> LogicInfoUtils.getLogicInfoNoAnd(
|
||||||
|
wrapper.getIndex(), wrapper.getJoinClass(), wrapper.isHasAlias(), wrapper.getAlias()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value.append(StringPool.SPACE)
|
||||||
|
.append(wrapper.getKeyWord())
|
||||||
|
.append(StringPool.SPACE)
|
||||||
|
.append(wrapper.getTableName())
|
||||||
|
.append(StringPool.SPACE)
|
||||||
|
.append(wrapper.hasAlias ? wrapper.alias : (wrapper.alias + wrapper.getIndex()))
|
||||||
|
.append(Constant.ON)
|
||||||
|
.append(wrapper.getExpression().getNormal().getSqlSegment());
|
||||||
|
} else {
|
||||||
|
value.append(StringPool.SPACE)
|
||||||
|
.append(wrapper.getKeyWord())
|
||||||
|
.append(StringPool.SPACE)
|
||||||
|
.append(wrapper.from.getStringValue())
|
||||||
|
.append(StringPool.SPACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
from.setStringValue(value.toString());
|
||||||
|
}
|
||||||
|
return from.getStringValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检验表是否已连接
|
||||||
|
*/
|
||||||
|
public boolean checkJoinTable(Class<?> clazz) {
|
||||||
|
return onWrappers.stream().anyMatch(wrapper -> {
|
||||||
|
if (Objects.equals(wrapper.getJoinClass(), clazz)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
TableInfo info = TableHelper.getAssert(clazz);
|
||||||
|
String tableName = info.getTableName();
|
||||||
|
return Optional.ofNullable(wrapper.from.getStringValue())
|
||||||
|
.map(w -> w.contains(Constant.JOIN + StringPool.SPACE + tableName + StringPool.SPACE))
|
||||||
|
.orElse(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部调用, 不建议使用
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public <R> Children join(String keyWord, BaseColumn<R> baseColumn, MFunction<AptAbstractWrapper<T, ?>> function) {
|
||||||
|
Integer oldIndex = this.getIndex();
|
||||||
|
int newIndex = tableIndex;
|
||||||
|
TableInfo info = TableHelper.getAssert(baseColumn.getColumnClass());
|
||||||
|
Children instance = instance(newIndex, keyWord, baseColumn.getColumnClass(), info.getTableName());
|
||||||
|
instance.isMain = false;
|
||||||
|
onWrappers.add(instance);
|
||||||
|
if (StringUtils.isBlank(baseColumn.getAlias())) {
|
||||||
|
aptIndex.put(baseColumn, subTableAlias + newIndex);
|
||||||
|
instance.alias = subTableAlias;
|
||||||
|
instance.hasAlias = false;
|
||||||
|
} else {
|
||||||
|
aptIndex.put(baseColumn, baseColumn.getAlias());
|
||||||
|
instance.alias = baseColumn.getAlias();
|
||||||
|
instance.hasAlias = true;
|
||||||
|
}
|
||||||
|
tableIndex++;
|
||||||
|
function.apply(instance);
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义关键词连接
|
||||||
|
*
|
||||||
|
* @param keyWord 连表关键词
|
||||||
|
* @param condition 条件
|
||||||
|
* @param joinSql sql
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Children join(String keyWord, boolean condition, String joinSql) {
|
||||||
|
if (condition) {
|
||||||
|
Children wrapper = instanceEmpty();
|
||||||
|
wrapper.from.setStringValue(joinSql);
|
||||||
|
wrapper.keyWord = keyWord;
|
||||||
|
onWrappers.add(wrapper);
|
||||||
|
}
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否使用默认注解 {@link OrderBy} 排序
|
||||||
|
*
|
||||||
|
* @return true 使用 false 不使用
|
||||||
|
*/
|
||||||
|
public boolean isUseAnnotationOrderBy() {
|
||||||
|
final String _sqlSegment = this.getSqlSegment();
|
||||||
|
if (StringUtils.isBlank(_sqlSegment)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
final String _sqlSegmentToUpperCase = _sqlSegment.toUpperCase();
|
||||||
|
return !(_sqlSegmentToUpperCase.contains(Constants.ORDER_BY)
|
||||||
|
|| _sqlSegmentToUpperCase.contains(Constants.LIMIT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 必要的初始化
|
||||||
|
*/
|
||||||
|
protected void initNeed() {
|
||||||
|
paramNameSeq = new AtomicInteger(0);
|
||||||
|
paramNameValuePairs = new HashMap<>(16);
|
||||||
|
expression = new MergeSegments();
|
||||||
|
lastSql = SharedString.emptyString();
|
||||||
|
sqlComment = SharedString.emptyString();
|
||||||
|
sqlFirst = SharedString.emptyString();
|
||||||
|
aptIndex = new TableMap<>(this.baseColumn, this.alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
super.clear();
|
||||||
|
this.alias = ConfigProperties.tableAlias;
|
||||||
|
this.resultMap = false;
|
||||||
|
this.tableIndex = 1;
|
||||||
|
this.dynamicTableName = false;
|
||||||
|
this.tableFunc = null;
|
||||||
|
this.logicDelType = ConfigProperties.logicDelType;
|
||||||
|
this.from.toEmpty();
|
||||||
|
this.hasAlias = false;
|
||||||
|
this.keyWord = null;
|
||||||
|
this.logicSql = true;
|
||||||
|
this.isMain = true;
|
||||||
|
this.checkSqlInjection = false;
|
||||||
|
this.onWrappers.clear();
|
||||||
|
this.aptIndex.clear();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,341 @@
|
|||||||
|
package com.github.yulichang.wrapper.apt;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.SharedString;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
import com.github.yulichang.config.ConfigProperties;
|
||||||
|
import com.github.yulichang.toolkit.LambdaUtils;
|
||||||
|
import com.github.yulichang.toolkit.*;
|
||||||
|
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||||
|
import com.github.yulichang.wrapper.apt.interfaces.Query;
|
||||||
|
import com.github.yulichang.wrapper.apt.interfaces.QueryLabel;
|
||||||
|
import com.github.yulichang.wrapper.enums.IfExistsSqlKeyWordEnum;
|
||||||
|
import com.github.yulichang.wrapper.interfaces.Chain;
|
||||||
|
import com.github.yulichang.wrapper.interfaces.SelectWrapper;
|
||||||
|
import com.github.yulichang.wrapper.resultmap.Label;
|
||||||
|
import com.github.yulichang.wrapper.segments.Select;
|
||||||
|
import com.github.yulichang.wrapper.segments.SelectApt;
|
||||||
|
import com.github.yulichang.wrapper.segments.SelectCache;
|
||||||
|
import com.github.yulichang.wrapper.segments.SelectSub;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lambda 语法使用 Wrapper
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.5.0
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class AptQueryWrapper<T> extends AptAbstractWrapper<T, AptQueryWrapper<T>> implements
|
||||||
|
Query<AptQueryWrapper<T>>, QueryLabel<AptQueryWrapper<T>>, Chain<T>, SelectWrapper<T, AptQueryWrapper<T>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询字段 sql
|
||||||
|
*/
|
||||||
|
private SharedString sqlSelect = new SharedString();
|
||||||
|
/**
|
||||||
|
* 是否 select distinct
|
||||||
|
*/
|
||||||
|
private boolean selectDistinct = false;
|
||||||
|
/**
|
||||||
|
* 查询的字段
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private final List<Select> selectColumns = new ArrayList<>();
|
||||||
|
/**
|
||||||
|
* 映射关系
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private final List<Label<?>> resultMapMybatisLabel = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* union sql
|
||||||
|
*/
|
||||||
|
private SharedString unionSql;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义wrapper索引
|
||||||
|
*/
|
||||||
|
private AtomicInteger wrapperIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义wrapper
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private Map<String, Wrapper<?>> wrapperMap;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推荐使用此构造方法
|
||||||
|
*/
|
||||||
|
public AptQueryWrapper(BaseColumn<T> baseColumn) {
|
||||||
|
super(baseColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AptQueryWrapper(BaseColumn<T> baseColumn, T entity) {
|
||||||
|
super(baseColumn, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不建议直接 new 该实例,使用 JoinWrappers.lambda(UserDO.class)
|
||||||
|
*/
|
||||||
|
protected AptQueryWrapper(T entity, BaseColumn<T> baseColumn, SharedString sqlSelect, AtomicInteger paramNameSeq,
|
||||||
|
Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments, SharedString paramAlias,
|
||||||
|
SharedString lastSql, SharedString sqlComment, SharedString sqlFirst,
|
||||||
|
TableMap<BaseColumn<?>, String> aptIndex, Integer index, String keyWord, Class<?> joinClass, String tableName,
|
||||||
|
BiPredicate<Object, IfExistsSqlKeyWordEnum> IfExists) {
|
||||||
|
super(baseColumn);
|
||||||
|
super.setEntity(entity);
|
||||||
|
super.setEntityClass(baseColumn.getColumnClass());
|
||||||
|
this.baseColumn = baseColumn;
|
||||||
|
this.paramNameSeq = paramNameSeq;
|
||||||
|
this.paramNameValuePairs = paramNameValuePairs;
|
||||||
|
this.expression = mergeSegments;
|
||||||
|
this.sqlSelect = sqlSelect;
|
||||||
|
this.paramAlias = paramAlias;
|
||||||
|
this.lastSql = lastSql;
|
||||||
|
this.sqlComment = sqlComment;
|
||||||
|
this.sqlFirst = sqlFirst;
|
||||||
|
this.aptIndex = aptIndex;
|
||||||
|
this.index = index;
|
||||||
|
this.keyWord = keyWord;
|
||||||
|
this.joinClass = joinClass;
|
||||||
|
this.tableName = tableName;
|
||||||
|
this.ifExists = IfExists;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sql去重
|
||||||
|
* select distinct
|
||||||
|
*/
|
||||||
|
public AptQueryWrapper<T> distinct() {
|
||||||
|
this.selectDistinct = true;
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Select> getSelectColum() {
|
||||||
|
return this.selectColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLabel(Label<?> label) {
|
||||||
|
this.resultMap = true;
|
||||||
|
this.resultMapMybatisLabel.add(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AptQueryWrapper<T> getChildren() {
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置查询字段
|
||||||
|
*
|
||||||
|
* @param columns 字段数组
|
||||||
|
* @return children
|
||||||
|
*/
|
||||||
|
public final AptQueryWrapper<T> select(Column... columns) {
|
||||||
|
if (ArrayUtils.isNotEmpty(columns)) {
|
||||||
|
for (Column s : columns) {
|
||||||
|
Map<String, SelectCache> cacheMap = ColumnCache.getMapField(s.getClazz());
|
||||||
|
SelectCache cache = cacheMap.get(s.getProperty());
|
||||||
|
getSelectColum().add(new SelectApt(cache, s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询实体类全部字段
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final <E> AptQueryWrapper<T> selectAll(BaseColumn<E> baseColumn, Column... exclude) {
|
||||||
|
return Query.super.selectAll(baseColumn, exclude);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询主表全部字段
|
||||||
|
* <p>
|
||||||
|
* 需要使用 使用 JoinWrappers.lambda(clazz) 或者 new MPJLambdaQueryWrapper<<(clazz) 构造
|
||||||
|
*
|
||||||
|
* @return children
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AptQueryWrapper<T> selectAll() {
|
||||||
|
Assert.notNull(getEntityClass(), "使用 JoinWrappers.apt(clazz) 或者 new JoinAptQueryWrapper<>(BaseColum)");
|
||||||
|
return selectAll(getBaseColumn());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子查询
|
||||||
|
*/
|
||||||
|
public <E, F> AptQueryWrapper<T> selectSub(BaseColumn<E> baseColumn, Consumer<AptQueryWrapper<E>> consumer, SFunction<F, ?> alias) {
|
||||||
|
return selectSub(baseColumn, ConfigProperties.subQueryAlias, consumer, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子查询
|
||||||
|
*/
|
||||||
|
public <E, F> AptQueryWrapper<T> selectSub(BaseColumn<E> baseColumn, String st, Consumer<AptQueryWrapper<E>> consumer, SFunction<F, ?> alias) {
|
||||||
|
AptQueryWrapper<E> wrapper = new AptQueryWrapper<E>(null, baseColumn, SharedString.emptyString(),
|
||||||
|
paramNameSeq, paramNameValuePairs, new MergeSegments(), new SharedString(this.paramAlias
|
||||||
|
.getStringValue()), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(),
|
||||||
|
this.aptIndex, null, null, null, null, ifExists) {
|
||||||
|
};
|
||||||
|
wrapper.alias = st;
|
||||||
|
wrapper.subTableAlias = st;
|
||||||
|
consumer.accept(wrapper);
|
||||||
|
addCustomWrapper(wrapper);
|
||||||
|
String name = LambdaUtils.getName(alias);
|
||||||
|
this.selectColumns.add(new SelectSub(() -> AptWrapperUtils.buildSubSqlByWrapper(baseColumn.getColumnClass(), wrapper, name), hasAlias, this.alias, name));
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* union
|
||||||
|
* <p>
|
||||||
|
* 例: wrapper.union(UserDO.class, union -> union.selectAll(UserDO.class))
|
||||||
|
*
|
||||||
|
* @param baseColumn union语句的主表类型
|
||||||
|
* @since 1.4.8
|
||||||
|
*/
|
||||||
|
public <U> AptQueryWrapper<T> union(BaseColumn<U> baseColumn, Consumer<AptQueryWrapper<U>> consumer) {
|
||||||
|
AptQueryWrapper<U> unionWrapper = JoinWrappers.apt(baseColumn);
|
||||||
|
addCustomWrapper(unionWrapper);
|
||||||
|
consumer.accept(unionWrapper);
|
||||||
|
|
||||||
|
String sb = " UNION " + AptWrapperUtils.buildUnionSqlByWrapper(baseColumn.getColumnClass(), unionWrapper);
|
||||||
|
|
||||||
|
if (Objects.isNull(unionSql)) {
|
||||||
|
unionSql = SharedString.emptyString();
|
||||||
|
}
|
||||||
|
unionSql.setStringValue(unionSql.getStringValue() + sb);
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* union
|
||||||
|
* <p>
|
||||||
|
* 例: wrapper.unionAll(UserDO.class, union -> union.selectAll(UserDO.class))
|
||||||
|
*
|
||||||
|
* @param baseColumn union语句的主表类型
|
||||||
|
* @since 1.4.8
|
||||||
|
*/
|
||||||
|
public <U> AptQueryWrapper<T> unionAll(BaseColumn<U> baseColumn, Consumer<AptQueryWrapper<U>> consumer) {
|
||||||
|
AptQueryWrapper<U> unionWrapper = JoinWrappers.apt(baseColumn);
|
||||||
|
addCustomWrapper(unionWrapper);
|
||||||
|
consumer.accept(unionWrapper);
|
||||||
|
|
||||||
|
String sb = " UNION ALL " + AptWrapperUtils.buildUnionSqlByWrapper(baseColumn.getColumnClass(), unionWrapper);
|
||||||
|
|
||||||
|
if (Objects.isNull(unionSql)) {
|
||||||
|
unionSql = SharedString.emptyString();
|
||||||
|
}
|
||||||
|
unionSql.setStringValue(unionSql.getStringValue() + sb);
|
||||||
|
return typedThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addCustomWrapper(AptQueryWrapper<?> wrapper) {
|
||||||
|
if (Objects.isNull(wrapperIndex)) {
|
||||||
|
wrapperIndex = new AtomicInteger(0);
|
||||||
|
}
|
||||||
|
int index = wrapperIndex.incrementAndGet();
|
||||||
|
if (Objects.isNull(wrapperMap)) {
|
||||||
|
wrapperMap = new HashMap<>();
|
||||||
|
}
|
||||||
|
String key = "ew" + index;
|
||||||
|
wrapper.setParamAlias(wrapper.getParamAlias() + ".wrapperMap." + key);
|
||||||
|
wrapperMap.put(key, wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询条件 SQL 片段
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getSqlSelect() {
|
||||||
|
if (StringUtils.isBlank(sqlSelect.getStringValue()) && CollectionUtils.isNotEmpty(selectColumns)) {
|
||||||
|
String s = selectColumns.stream().map(i -> {
|
||||||
|
if (i.isStr()) {
|
||||||
|
return i.getColumn();
|
||||||
|
}
|
||||||
|
if (i.isFunc()) {
|
||||||
|
return String.format(i.getFunc().getSql(), Arrays.stream(i.getColumns()).map(c ->
|
||||||
|
getPrefix(c.getRoot()) + StringPool.DOT + i.getColumn()).toArray()) + Constant.AS + i.getAlias();
|
||||||
|
} else {
|
||||||
|
String prefix;
|
||||||
|
if (null == i.getTableAlias() && null != i.getBaseColumn()) {
|
||||||
|
prefix = getPrefix(i.getBaseColumn());
|
||||||
|
} else {
|
||||||
|
prefix = i.getTableAlias();
|
||||||
|
}
|
||||||
|
String col = prefix + StringPool.DOT + i.getColumn();
|
||||||
|
return i.isHasAlias() ? col + Constants.AS + i.getAlias() : col;
|
||||||
|
}
|
||||||
|
}).collect(Collectors.joining(StringPool.COMMA));
|
||||||
|
sqlSelect.setStringValue(s);
|
||||||
|
}
|
||||||
|
return sqlSelect.getStringValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUnionSql() {
|
||||||
|
return Optional.ofNullable(unionSql).map(SharedString::getStringValue).orElse(StringPool.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getSelectDistinct() {
|
||||||
|
return selectDistinct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于生成嵌套 sql
|
||||||
|
* <p>故 sqlSelect 不向下传递</p>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected AptQueryWrapper<T> instance() {
|
||||||
|
return instance(index, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AptQueryWrapper<T> instanceEmpty() {
|
||||||
|
return new AptQueryWrapper<>(getBaseColumn());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AptQueryWrapper<T> instance(Integer index, String keyWord, Class<?> joinClass, String tableName) {
|
||||||
|
return new AptQueryWrapper<>(getEntity(), baseColumn, null, paramNameSeq, paramNameValuePairs,
|
||||||
|
new MergeSegments(), this.paramAlias, SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(),
|
||||||
|
this.aptIndex, index, keyWord, joinClass, tableName, ifExists);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
super.clear();
|
||||||
|
selectDistinct = false;
|
||||||
|
sqlSelect.toNull();
|
||||||
|
selectColumns.clear();
|
||||||
|
wrapperIndex = new AtomicInteger(0);
|
||||||
|
if (Objects.nonNull(wrapperMap)) wrapperMap.clear();
|
||||||
|
if (Objects.nonNull(unionSql)) unionSql.toEmpty();
|
||||||
|
resultMapMybatisLabel.clear();
|
||||||
|
ifExists = ConfigProperties.ifExists;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,98 @@
|
|||||||
|
package com.github.yulichang.wrapper.apt.interfaces;
|
||||||
|
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将原来的泛型R改成Column
|
||||||
|
* <p>
|
||||||
|
* {@link com.baomidou.mybatisplus.core.conditions.interfaces.Compare}
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public interface Compare<Children> extends Serializable {
|
||||||
|
|
||||||
|
default Children eq(Column column, Object val) {
|
||||||
|
return eq(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children eq(boolean condition, Column column, Object val);
|
||||||
|
|
||||||
|
default Children ne(Column column, Object val) {
|
||||||
|
return ne(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children ne(boolean condition, Column column, Object val);
|
||||||
|
|
||||||
|
default Children gt(Column column, Object val) {
|
||||||
|
return gt(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children gt(boolean condition, Column column, Object val);
|
||||||
|
|
||||||
|
default Children ge(Column column, Object val) {
|
||||||
|
return ge(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children ge(boolean condition, Column column, Object val);
|
||||||
|
|
||||||
|
default Children lt(Column column, Object val) {
|
||||||
|
return lt(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children lt(boolean condition, Column column, Object val);
|
||||||
|
|
||||||
|
default Children le(Column column, Object val) {
|
||||||
|
return le(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children le(boolean condition, Column column, Object val);
|
||||||
|
|
||||||
|
default Children between(Column column, Object val1, Object val2) {
|
||||||
|
return between(true, column, val1, val2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children between(boolean condition, Column column, Object val1, Object val2);
|
||||||
|
|
||||||
|
default Children notBetween(Column column, Object val1, Object val2) {
|
||||||
|
return notBetween(true, column, val1, val2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children notBetween(boolean condition, Column column, Object val1, Object val2);
|
||||||
|
|
||||||
|
default Children like(Column column, Object val) {
|
||||||
|
return like(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children like(boolean condition, Column column, Object val);
|
||||||
|
|
||||||
|
default Children notLike(Column column, Object val) {
|
||||||
|
return notLike(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children notLike(boolean condition, Column column, Object val);
|
||||||
|
|
||||||
|
default Children likeLeft(Column column, Object val) {
|
||||||
|
return likeLeft(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children likeLeft(boolean condition, Column column, Object val);
|
||||||
|
|
||||||
|
default Children notLikeLeft(Column column, Object val) {
|
||||||
|
return notLikeLeft(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children notLikeLeft(boolean condition, Column column, Object val);
|
||||||
|
|
||||||
|
default Children likeRight(Column column, Object val) {
|
||||||
|
return likeRight(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children likeRight(boolean condition, Column column, Object val);
|
||||||
|
|
||||||
|
default Children notLikeRight(Column column, Object val) {
|
||||||
|
return notLikeRight(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children notLikeRight(boolean condition, Column column, Object val);
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
package com.github.yulichang.wrapper.apt.interfaces;
|
||||||
|
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
import com.github.yulichang.wrapper.enums.IfExistsSqlKeyWordEnum;
|
||||||
|
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link com.baomidou.mybatisplus.core.conditions.interfaces.Compare}
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.4.9
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public interface CompareIfExists<Children> extends Compare<Children> {
|
||||||
|
|
||||||
|
BiPredicate<Object, IfExistsSqlKeyWordEnum> getIfExists();
|
||||||
|
|
||||||
|
default Children eqIfExists(Column column, Object val) {
|
||||||
|
return eq(getIfExists().test(val, IfExistsSqlKeyWordEnum.EQ), column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children neIfExists(Column column, Object val) {
|
||||||
|
return ne(getIfExists().test(val, IfExistsSqlKeyWordEnum.NE), column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children gtIfExists(Column column, Object val) {
|
||||||
|
return gt(getIfExists().test(val, IfExistsSqlKeyWordEnum.GT), column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children geIfExists(Column column, Object val) {
|
||||||
|
return ge(getIfExists().test(val, IfExistsSqlKeyWordEnum.GE), column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children ltIfExists(Column column, Object val) {
|
||||||
|
return lt(getIfExists().test(val, IfExistsSqlKeyWordEnum.LT), column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children leIfExists(Column column, Object val) {
|
||||||
|
return le(getIfExists().test(val, IfExistsSqlKeyWordEnum.LE), column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children likeIfExists(Column column, Object val) {
|
||||||
|
return like(getIfExists().test(val, IfExistsSqlKeyWordEnum.LIKE), column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children notLikeIfExists(Column column, Object val) {
|
||||||
|
return notLike(getIfExists().test(val, IfExistsSqlKeyWordEnum.NOT_LIKE), column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children likeLeftIfExists(Column column, Object val) {
|
||||||
|
return likeLeft(getIfExists().test(val, IfExistsSqlKeyWordEnum.LIKE_LEFT), column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children notLikeLeftIfExists(Column column, Object val) {
|
||||||
|
return notLikeLeft(getIfExists().test(val, IfExistsSqlKeyWordEnum.NOT_LIKE_LEFT), column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children likeRightIfExists(Column column, Object val) {
|
||||||
|
return likeRight(getIfExists().test(val, IfExistsSqlKeyWordEnum.LIKE_RIGHT), column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children notLikeRightIfExists(Column column, Object val) {
|
||||||
|
return notLikeRight(getIfExists().test(val, IfExistsSqlKeyWordEnum.NOT_LIKE_RIGHT), column, val);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,190 @@
|
|||||||
|
package com.github.yulichang.wrapper.apt.interfaces;
|
||||||
|
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将原来的泛型R改成Column
|
||||||
|
* <p>
|
||||||
|
* copy {@link com.baomidou.mybatisplus.core.conditions.interfaces.Func}
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public interface Func<Children> extends Serializable {
|
||||||
|
|
||||||
|
|
||||||
|
default Children isNull(Column column) {
|
||||||
|
return isNull(true, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children isNull(boolean condition, Column column);
|
||||||
|
|
||||||
|
|
||||||
|
default Children isNotNull(Column column) {
|
||||||
|
return isNotNull(true, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children isNotNull(boolean condition, Column column);
|
||||||
|
|
||||||
|
|
||||||
|
default Children in(Column column, Collection<?> coll) {
|
||||||
|
return in(true, column, coll);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children in(boolean condition, Column column, Collection<?> coll);
|
||||||
|
|
||||||
|
|
||||||
|
default Children in(Column column, Object... values) {
|
||||||
|
return in(true, column, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children in(boolean condition, Column column, Object... values);
|
||||||
|
|
||||||
|
|
||||||
|
default Children notIn(Column column, Collection<?> coll) {
|
||||||
|
return notIn(true, column, coll);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children notIn(boolean condition, Column column, Collection<?> coll);
|
||||||
|
|
||||||
|
|
||||||
|
default Children notIn(Column column, Object... values) {
|
||||||
|
return notIn(true, column, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children notIn(boolean condition, Column column, Object... values);
|
||||||
|
|
||||||
|
|
||||||
|
default Children inSql(Column column, String inValue) {
|
||||||
|
return inSql(true, column, inValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children inSql(boolean condition, Column column, String inValue);
|
||||||
|
|
||||||
|
|
||||||
|
default Children notInSql(Column column, String inValue) {
|
||||||
|
return notInSql(true, column, inValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children notInSql(boolean condition, Column column, String inValue);
|
||||||
|
|
||||||
|
default Children gtSql(Column column, String inValue) {
|
||||||
|
return gtSql(true, column, inValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children gtSql(boolean condition, Column column, String inValue);
|
||||||
|
|
||||||
|
default Children geSql(Column column, String inValue) {
|
||||||
|
return geSql(true, column, inValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children geSql(boolean condition, Column column, String inValue);
|
||||||
|
|
||||||
|
default Children ltSql(Column column, String inValue) {
|
||||||
|
return ltSql(true, column, inValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children ltSql(boolean condition, Column column, String inValue);
|
||||||
|
|
||||||
|
default Children leSql(Column column, String inValue) {
|
||||||
|
return leSql(true, column, inValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children leSql(boolean condition, Column column, String inValue);
|
||||||
|
|
||||||
|
default Children eqSql(Column column, String inValue) {
|
||||||
|
return eqSql(true, column, inValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children eqSql(boolean condition, Column column, String inValue);
|
||||||
|
|
||||||
|
default Children groupBy(Column column) {
|
||||||
|
return groupBy(true, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children groupBy(List<Column> column) {
|
||||||
|
return groupBy(true, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children groupBy(boolean condition, List<Column> columns);
|
||||||
|
|
||||||
|
default Children groupBy(Column column, Column... columns) {
|
||||||
|
return groupBy(true, column, columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children groupBy(boolean condition, Column column, Column... columns);
|
||||||
|
|
||||||
|
|
||||||
|
default Children orderByAsc(Column column) {
|
||||||
|
return orderByAsc(true, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children orderByAsc(List<Column> columns) {
|
||||||
|
return orderByAsc(true, columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children orderByAsc(boolean condition, List<Column> columns);
|
||||||
|
|
||||||
|
|
||||||
|
default Children orderByAsc(Column column, Column... columns) {
|
||||||
|
return orderByAsc(true, column, columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default Children orderByAsc(boolean condition, Column column, Column... columns) {
|
||||||
|
return orderBy(condition, true, column, columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children orderByDesc(Column column) {
|
||||||
|
return orderByDesc(true, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children orderByDesc(List<Column> columns) {
|
||||||
|
return orderByDesc(true, columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children orderByDesc(boolean condition, List<Column> columns);
|
||||||
|
|
||||||
|
default Children orderByDesc(Column column, Column... columns) {
|
||||||
|
return orderByDesc(true, column, columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Children orderByDesc(boolean condition, Column column, Column... columns) {
|
||||||
|
return orderBy(condition, false, column, columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
Children orderBy(boolean condition, boolean isAsc, Column column, Column... columns);
|
||||||
|
|
||||||
|
default Children having(String sqlHaving, Object... params) {
|
||||||
|
return having(true, sqlHaving, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HAVING ( sql语句 )
|
||||||
|
* <p>例1: having("sum(age) > 10")</p>
|
||||||
|
* <p>例2: having("sum(age) > {0}", 10)</p>
|
||||||
|
*
|
||||||
|
* @param condition 执行条件
|
||||||
|
* @param sqlHaving sql 语句
|
||||||
|
* @param params 参数数组
|
||||||
|
* @return children
|
||||||
|
*/
|
||||||
|
Children having(boolean condition, String sqlHaving, Object... params);
|
||||||
|
|
||||||
|
|
||||||
|
default Children func(Consumer<Children> consumer) {
|
||||||
|
return func(true, consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消费函数
|
||||||
|
*
|
||||||
|
* @param consumer 消费函数
|
||||||
|
* @return children
|
||||||
|
* @since 3.3.1
|
||||||
|
*/
|
||||||
|
Children func(boolean condition, Consumer<Children> consumer);
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
package com.github.yulichang.wrapper.apt.interfaces;
|
||||||
|
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将原来的泛型R改成Column, Object改为Column
|
||||||
|
* 以及移除不会在ON语句中出现的条件 比如like相关 保留原来的like 只是不太可能会出现 on a.id like b.id 所以不会支持这种写法
|
||||||
|
* <p>
|
||||||
|
* {@link com.baomidou.mybatisplus.core.conditions.interfaces.Compare}
|
||||||
|
*
|
||||||
|
* @since 1.1.8
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public interface OnCompare<Children> extends Serializable {
|
||||||
|
|
||||||
|
default Children eq(Column column, Column val) {
|
||||||
|
return eq(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 等于 =
|
||||||
|
*
|
||||||
|
* @param condition 执行条件
|
||||||
|
* @param column 字段
|
||||||
|
* @param val 值
|
||||||
|
* @return children
|
||||||
|
*/
|
||||||
|
Children eq(boolean condition, Column column, Column val);
|
||||||
|
|
||||||
|
default Children ne(Column column, Column val) {
|
||||||
|
return ne(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不等于 <>
|
||||||
|
*
|
||||||
|
* @param condition 执行条件
|
||||||
|
* @param column 字段
|
||||||
|
* @param val 值
|
||||||
|
* @return children
|
||||||
|
*/
|
||||||
|
Children ne(boolean condition, Column column, Column val);
|
||||||
|
|
||||||
|
default Children gt(Column column, Column val) {
|
||||||
|
return gt(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 大于 >
|
||||||
|
*
|
||||||
|
* @param condition 执行条件
|
||||||
|
* @param column 字段
|
||||||
|
* @param val 值
|
||||||
|
* @return children
|
||||||
|
*/
|
||||||
|
Children gt(boolean condition, Column column, Column val);
|
||||||
|
|
||||||
|
default Children ge(Column column, Column val) {
|
||||||
|
return ge(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 大于等于 >=
|
||||||
|
*
|
||||||
|
* @param condition 执行条件
|
||||||
|
* @param column 字段
|
||||||
|
* @param val 值
|
||||||
|
* @return children
|
||||||
|
*/
|
||||||
|
Children ge(boolean condition, Column column, Column val);
|
||||||
|
|
||||||
|
default Children lt(Column column, Column val) {
|
||||||
|
return lt(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小于 <
|
||||||
|
*
|
||||||
|
* @param condition 执行条件
|
||||||
|
* @param column 字段
|
||||||
|
* @param val 值
|
||||||
|
* @return children
|
||||||
|
*/
|
||||||
|
Children lt(boolean condition, Column column, Column val);
|
||||||
|
|
||||||
|
default Children le(Column column, Column val) {
|
||||||
|
return le(true, column, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小于等于 <=
|
||||||
|
*
|
||||||
|
* @param condition 执行条件
|
||||||
|
* @param column 字段
|
||||||
|
* @param val 值
|
||||||
|
* @return children
|
||||||
|
*/
|
||||||
|
Children le(boolean condition, Column column, Column val);
|
||||||
|
}
|
@ -0,0 +1,283 @@
|
|||||||
|
package com.github.yulichang.wrapper.apt.interfaces;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
import com.github.yulichang.toolkit.Constant;
|
||||||
|
import com.github.yulichang.toolkit.LambdaUtils;
|
||||||
|
import com.github.yulichang.toolkit.MPJReflectionKit;
|
||||||
|
import com.github.yulichang.toolkit.TableHelper;
|
||||||
|
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||||
|
import com.github.yulichang.toolkit.support.FieldCache;
|
||||||
|
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
||||||
|
import com.github.yulichang.wrapper.enums.DefaultFuncEnum;
|
||||||
|
import com.github.yulichang.wrapper.segments.*;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参考 {@link com.baomidou.mybatisplus.core.conditions.query.Query}
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unused"})
|
||||||
|
public interface Query<Children> extends Serializable {
|
||||||
|
|
||||||
|
List<Select> getSelectColum();
|
||||||
|
|
||||||
|
Children getChildren();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤查询的字段信息
|
||||||
|
* <p>例1: 只要 java 字段名以 "test" 开头的 -> select(i -> i.getProperty().startsWith("test"))</p>
|
||||||
|
* <p>例2: 只要 java 字段属性是 CharSequence 类型的 -> select(TableFieldInfo::isCharSequence)</p>
|
||||||
|
* <p>例3: 只要 java 字段没有填充策略的 -> select(i -> i.getFieldFill() == FieldFill.DEFAULT)</p>
|
||||||
|
* <p>例4: 要全部字段 -> select(i -> true)</p>
|
||||||
|
* <p>例5: 只要主键字段 -> select(i -> false)</p>
|
||||||
|
*
|
||||||
|
* @param predicate 过滤方式
|
||||||
|
* @return children
|
||||||
|
*/
|
||||||
|
default <E> Children selectFilter(BaseColumn<E> baseColumn, Predicate<SelectCache> predicate) {
|
||||||
|
TableInfo info = TableHelper.getAssert(baseColumn.getColumnClass());
|
||||||
|
List<SelectCache> cacheList = ColumnCache.getListField(baseColumn.getColumnClass());
|
||||||
|
cacheList.stream().filter(SelectCache::isSelect).filter(predicate).collect(Collectors.toList()).forEach(
|
||||||
|
i -> getSelectColum().add(new SelectApt(i, baseColumn)));
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<E> Children select(Column... columns);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String 查询
|
||||||
|
*
|
||||||
|
* @param columns 列
|
||||||
|
*/
|
||||||
|
default Children select(String... columns) {
|
||||||
|
getSelectColum().add(new SelectString(String.join(StringPool.COMMA, columns), null));
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String 查询
|
||||||
|
*
|
||||||
|
* @param column 列
|
||||||
|
*/
|
||||||
|
default <E> Children selectAs(String column, SFunction<E, ?> alias) {
|
||||||
|
String name = LambdaUtils.getName(alias);
|
||||||
|
getSelectColum().add(new SelectString(column + Constant.AS + name, name));
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String 查询
|
||||||
|
*
|
||||||
|
* @param column 列
|
||||||
|
*/
|
||||||
|
default <X> Children selectAs(String index, Column column, SFunction<X, ?> alias) {
|
||||||
|
Map<String, SelectCache> cacheMap = ColumnCache.getMapField(column.getClazz());
|
||||||
|
SelectCache cache = cacheMap.get(column.getProperty());
|
||||||
|
String name = LambdaUtils.getName(alias);
|
||||||
|
getSelectColum().add(new SelectApt(cache, column, name));
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default <E> Children selectAsClass(BaseColumn<E> baseColumn, Class<?> tag) {
|
||||||
|
Map<String, SelectCache> normalMap = ColumnCache.getMapField(baseColumn.getColumnClass());
|
||||||
|
List<FieldCache> fieldList = MPJReflectionKit.getFieldList(tag);
|
||||||
|
for (FieldCache cache : fieldList) {
|
||||||
|
if (normalMap.containsKey(cache.getField().getName())) {
|
||||||
|
SelectCache selectCache = normalMap.get(cache.getField().getName());
|
||||||
|
if (selectCache.isSelect()) {
|
||||||
|
getSelectColum().add(new SelectApt(selectCache, baseColumn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ignore
|
||||||
|
*/
|
||||||
|
default <X> Children selectAs(Column column, SFunction<X, ?> alias) {
|
||||||
|
return selectAs(column, LambdaUtils.getName(alias));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 别名查询
|
||||||
|
*/
|
||||||
|
default <S> Children selectAs(Column column, String alias) {
|
||||||
|
Map<String, SelectCache> cacheMap = ColumnCache.getMapField(column.getClazz());
|
||||||
|
SelectCache cache = cacheMap.get(column.getProperty());
|
||||||
|
getSelectColum().add(new SelectApt(cache, column, alias));
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询实体类全部字段
|
||||||
|
*/
|
||||||
|
default <E> Children selectAll(BaseColumn<E> baseColumn) {
|
||||||
|
getSelectColum().addAll(ColumnCache.getListField(baseColumn.getColumnClass()).stream().filter(SelectCache::isSelect).map(i ->
|
||||||
|
new SelectApt(i, baseColumn)).collect(Collectors.toList()));
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询实体类全部字段
|
||||||
|
*
|
||||||
|
* @param baseColumn 查询的实体类
|
||||||
|
* @param exclude 排除字段
|
||||||
|
*/
|
||||||
|
default <E> Children selectAll(BaseColumn<E> baseColumn, Column... exclude) {
|
||||||
|
Set<String> excludeSet = Arrays.stream(exclude).map(i ->
|
||||||
|
i.getProperty().toUpperCase(Locale.ENGLISH)).collect(Collectors.toSet());
|
||||||
|
getSelectColum().addAll(ColumnCache.getListField(baseColumn.getColumnClass()).stream().filter(e -> e.isSelect() &&
|
||||||
|
!excludeSet.contains(e.getColumProperty().toUpperCase(Locale.ENGLISH))).map(i ->
|
||||||
|
new SelectApt(i, baseColumn)).collect(Collectors.toList()));
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* select sql 片段
|
||||||
|
*/
|
||||||
|
String getSqlSelect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聚合函数查询
|
||||||
|
* <p>
|
||||||
|
* wrapper.selectFunc(() -> "COUNT(%s)", "t.id", "total");
|
||||||
|
* <p>
|
||||||
|
* lambda
|
||||||
|
* wrapper.selectFunc(() -> "COUNT(%s)", UserDO::getId, UserDTO::getTotal);
|
||||||
|
*
|
||||||
|
* @param funcEnum 函数枚举 {@link DefaultFuncEnum}
|
||||||
|
* @param column 函数作用的字段
|
||||||
|
* @param alias 别名
|
||||||
|
*/
|
||||||
|
default <S> Children selectFunc(BaseFuncEnum funcEnum, Column column, String alias) {
|
||||||
|
Map<String, SelectCache> cacheMap = ColumnCache.getMapField(column.getClazz());
|
||||||
|
getSelectColum().add(new SelectApt(cacheMap.get(column.getProperty()), column, funcEnum, alias));
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectFunc(BaseFuncEnum funcEnum, Column column, SFunction<X, ?> alias) {
|
||||||
|
return selectFunc(funcEnum, column, LambdaUtils.getName(alias));
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S> Children selectFunc(BaseFuncEnum funcEnum, Column column) {
|
||||||
|
return selectFunc(funcEnum, column, column.getProperty());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default <X> Children selectFunc(String sql, Function<AptConsumer, Column[]> column, String alias) {
|
||||||
|
getSelectColum().add(new SelectApt(column.apply(AptConsumer.func), () -> sql, alias));
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
default <X, S> Children selectFunc(String sql, Function<AptConsumer, Column[]> column, SFunction<S, ?> alias) {
|
||||||
|
return selectFunc(sql, column, LambdaUtils.getName(alias));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 默认聚合函数扩展 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SUM()
|
||||||
|
*/
|
||||||
|
default <S> Children selectSum(Column column) {
|
||||||
|
return selectFunc(DefaultFuncEnum.SUM, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectSum(Column column, SFunction<X, ?> alias) {
|
||||||
|
return selectFunc(DefaultFuncEnum.SUM, column, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectSum(Column column, String alias) {
|
||||||
|
return selectFunc(DefaultFuncEnum.SUM, column, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COUNT()
|
||||||
|
*/
|
||||||
|
default <S> Children selectCount(Column column) {
|
||||||
|
return selectFunc(DefaultFuncEnum.COUNT, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectCount(Column column, SFunction<X, ?> alias) {
|
||||||
|
return selectFunc(DefaultFuncEnum.COUNT, column, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectCount(Column column, String alias) {
|
||||||
|
return selectFunc(DefaultFuncEnum.COUNT, column, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MAX()
|
||||||
|
*/
|
||||||
|
default <S> Children selectMax(Column column) {
|
||||||
|
return selectFunc(DefaultFuncEnum.MAX, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectMax(Column column, SFunction<X, ?> alias) {
|
||||||
|
return selectFunc(DefaultFuncEnum.MAX, column, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectMax(Column column, String alias) {
|
||||||
|
return selectFunc(DefaultFuncEnum.MAX, column, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIN()
|
||||||
|
*/
|
||||||
|
default <S> Children selectMin(Column column) {
|
||||||
|
return selectFunc(DefaultFuncEnum.MIN, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectMin(Column column, SFunction<X, ?> alias) {
|
||||||
|
return selectFunc(DefaultFuncEnum.MIN, column, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectMin(Column column, String alias) {
|
||||||
|
return selectFunc(DefaultFuncEnum.MIN, column, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIN()
|
||||||
|
*/
|
||||||
|
default <S> Children selectAvg(Column column) {
|
||||||
|
return selectFunc(DefaultFuncEnum.AVG, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectAvg(Column column, SFunction<X, ?> alias) {
|
||||||
|
return selectFunc(DefaultFuncEnum.AVG, column, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectAvg(Column column, String alias) {
|
||||||
|
return selectFunc(DefaultFuncEnum.AVG, column, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LEN()
|
||||||
|
*/
|
||||||
|
default <S> Children selectLen(Column column) {
|
||||||
|
return selectFunc(DefaultFuncEnum.LEN, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectLen(Column column, SFunction<X, ?> alias) {
|
||||||
|
return selectFunc(DefaultFuncEnum.LEN, column, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, X> Children selectLen(Column column, String alias) {
|
||||||
|
return selectFunc(DefaultFuncEnum.LEN, column, alias);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package com.github.yulichang.wrapper.apt.interfaces;
|
||||||
|
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||||
|
import com.github.yulichang.query.interfaces.StringJoin;
|
||||||
|
import com.github.yulichang.toolkit.Constant;
|
||||||
|
import com.github.yulichang.wrapper.apt.AptAbstractWrapper;
|
||||||
|
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yulichang
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, StringJoin<Children, Entity> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* left join
|
||||||
|
*
|
||||||
|
* @param clazz 关联的实体类
|
||||||
|
* @param left 条件
|
||||||
|
* @param right 条件
|
||||||
|
*/
|
||||||
|
default <T> Children leftJoin(BaseColumn<T> clazz, Column left, Column right) {
|
||||||
|
return join(Constant.LEFT_JOIN, clazz, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* left join 多条件
|
||||||
|
* <p>
|
||||||
|
* 例 leftJoin(UserDO.class, on -> on.eq(UserDO::getId,UserAddressDO::getUserId).le().gt()...)
|
||||||
|
*
|
||||||
|
* @param clazz 关联实体类
|
||||||
|
* @param function 条件`
|
||||||
|
*/
|
||||||
|
default <T> Children leftJoin(BaseColumn<T> clazz, MFunction<AptAbstractWrapper<Entity, ?>> function) {
|
||||||
|
return join(Constant.LEFT_JOIN, clazz, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ignore 参考 left join
|
||||||
|
*/
|
||||||
|
default <T> Children rightJoin(BaseColumn<T> clazz, Column left, Column right) {
|
||||||
|
return join(Constant.RIGHT_JOIN, clazz, left, right);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ignore 参考 left join
|
||||||
|
*/
|
||||||
|
default <T> Children rightJoin(BaseColumn<T> clazz, MFunction<AptAbstractWrapper<Entity, ?>> function) {
|
||||||
|
return join(Constant.RIGHT_JOIN, clazz, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ignore 参考 left join
|
||||||
|
*/
|
||||||
|
default <T> Children innerJoin(BaseColumn<T> clazz, Column left, Column right) {
|
||||||
|
return join(Constant.INNER_JOIN, clazz, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ignore 参考 left join
|
||||||
|
*/
|
||||||
|
default <T> Children innerJoin(BaseColumn<T> clazz, MFunction<AptAbstractWrapper<Entity, ?>> function) {
|
||||||
|
return join(Constant.INNER_JOIN, clazz, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义连表关键词
|
||||||
|
* 调用此方法 keyword 前后需要带空格 比如 " LEFT JOIN " " RIGHT JOIN "
|
||||||
|
* <p>
|
||||||
|
* 查询基类 可以直接调用此方法实现以上所有功能
|
||||||
|
*
|
||||||
|
* @param keyWord 连表关键字
|
||||||
|
* @param clazz 连表实体类
|
||||||
|
* @param left 关联条件
|
||||||
|
* @param right 扩展 用于关联表的 select 和 where
|
||||||
|
*/
|
||||||
|
default <T> Children join(String keyWord, BaseColumn<T> clazz, Column left, Column right) {
|
||||||
|
return join(keyWord, clazz, on -> on.eq(left, right));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部使用, 不建议直接调用
|
||||||
|
*/
|
||||||
|
<T> Children join(String keyWord, BaseColumn<T> clazz, MFunction<AptAbstractWrapper<Entity, ?>> function);
|
||||||
|
}
|
@ -0,0 +1,172 @@
|
|||||||
|
package com.github.yulichang.wrapper.apt.interfaces;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
|
import com.github.yulichang.toolkit.LambdaUtils;
|
||||||
|
import com.github.yulichang.toolkit.MPJReflectionKit;
|
||||||
|
import com.github.yulichang.toolkit.support.FieldCache;
|
||||||
|
import com.github.yulichang.wrapper.apt.resultmap.MybatisLabel;
|
||||||
|
import com.github.yulichang.wrapper.apt.resultmap.MybatisLabelFree;
|
||||||
|
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||||
|
import com.github.yulichang.wrapper.resultmap.Label;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对一或对多查询
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unchecked", "unused", "DuplicatedCode"})
|
||||||
|
public interface QueryLabel<Children> {
|
||||||
|
|
||||||
|
void addLabel(Label<?> label);
|
||||||
|
|
||||||
|
Children getChildren();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一对多查询 调用此方法必需要调用对应的 left join / right join ... 连表方法,否则会报错
|
||||||
|
* <p>
|
||||||
|
* 举例 UserDO AddressDO 为一对多关系 UserDTO 为结果类
|
||||||
|
* <pre>
|
||||||
|
* MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>();
|
||||||
|
* wrapper.selectAll(UserDO.class)
|
||||||
|
* .selectCollection(AddressDO.class, UserDTO::getAddressListDTO)
|
||||||
|
* .leftJoin(AddressDO.class, ...... )
|
||||||
|
* .eq(...)
|
||||||
|
* ...
|
||||||
|
* <pre/>
|
||||||
|
* 会自动将 AddressDO类中相同属性的字段 以mybatis<collection>的方式映射到UserDTO.addressListDTO属性中
|
||||||
|
*
|
||||||
|
* @since 1.3.0
|
||||||
|
*
|
||||||
|
* @param child 连表数据库实体类
|
||||||
|
* @param dtoField 包装类对应的属性
|
||||||
|
* @param <S> 包装类
|
||||||
|
* @param <C> 对多数据库实体类
|
||||||
|
* @param <Z> 包装类集合泛型
|
||||||
|
* @param <F> 包装类集合字段泛型
|
||||||
|
*/
|
||||||
|
|
||||||
|
default <S, C, Z, F extends Collection<?>> Children selectCollection(BaseColumn<C> child, SFunction<S, F> dtoField) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||||
|
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||||
|
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||||
|
FieldCache field = fieldMap.get(dtoFieldName);
|
||||||
|
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||||
|
MybatisLabel.Builder<C, Z> builder;
|
||||||
|
if (genericType == null || genericType.isAssignableFrom(child.getColumnClass())) {
|
||||||
|
//找不到集合泛型 List List<?> List<Object> , 直接查询数据库实体
|
||||||
|
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType());
|
||||||
|
} else {
|
||||||
|
Class<Z> ofType = (Class<Z>) genericType;
|
||||||
|
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), ofType, true);
|
||||||
|
}
|
||||||
|
addLabel(builder.build());
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一对多查询 调用此方法必需要调用对应的 left join / right join ... 连表方法,否则会报错
|
||||||
|
* <p>
|
||||||
|
* 举例 UserDO AddressDO 为一对多关系 UserDTO 为结果类
|
||||||
|
* <pre>
|
||||||
|
* MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
|
||||||
|
* .selectAll(UserDO.class)
|
||||||
|
* .selectCollection(AddressDO.class, UserDTO::getAddressListDTO, map -> map
|
||||||
|
* .id(AddressDO::getId, AddressDTO::getId) //如果属性名一致 可以传一个
|
||||||
|
* .result(AddressDO::getUserId) //如果属性名一致 可以传一个
|
||||||
|
* .result(AddressDO::getAddress, AddressDTO::getAddress)) //如果属性名一致 可以传一个
|
||||||
|
* .leftJoin(AddressDO.class, ...... )
|
||||||
|
* .eq(...)
|
||||||
|
* ...
|
||||||
|
* <pre/>
|
||||||
|
*
|
||||||
|
* 会自动将 AddressDO类中指定的字段 以mybatis<collection>的方式映射到UserDTO.addressListDTO属性中
|
||||||
|
*
|
||||||
|
* @since 1.3.0
|
||||||
|
*
|
||||||
|
* @param child 连表数据库实体类
|
||||||
|
* @param dtoField 包装类对应的属性
|
||||||
|
* @param collection collection标签内容
|
||||||
|
* @param <S> 包装类
|
||||||
|
* @param <C> 对多数据库实体类
|
||||||
|
* @param <Z> 包装类集合泛型
|
||||||
|
* @param <F> 包装类集合字段泛型
|
||||||
|
*/
|
||||||
|
default <S, C, Z, F extends Collection<Z>> Children selectCollection(BaseColumn<C> child,
|
||||||
|
SFunction<S, F> dtoField,
|
||||||
|
MFunction<MybatisLabel.Builder<C, Z>> collection) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||||
|
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||||
|
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||||
|
//获取集合泛型
|
||||||
|
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||||
|
Class<Z> ofType = (Class<Z>) genericType;
|
||||||
|
MybatisLabel.Builder<C, Z> builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), ofType, false);
|
||||||
|
MybatisLabel.Builder<C, Z> czBuilder = collection.apply(builder);
|
||||||
|
addLabel(czBuilder.build());
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default <S, Z, F extends Collection<Z>> Children selectCollection(SFunction<S, F> dtoField,
|
||||||
|
MFunction<MybatisLabelFree.Builder<Z>> collection) {
|
||||||
|
//自由映射必须存在泛型Z
|
||||||
|
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||||
|
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||||
|
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||||
|
//获取集合泛型
|
||||||
|
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||||
|
Class<Z> ofType = (Class<Z>) genericType;
|
||||||
|
MybatisLabelFree.Builder<Z> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), ofType);
|
||||||
|
MybatisLabelFree.Builder<Z> czBuilder = collection.apply(builder);
|
||||||
|
addLabel(czBuilder.build());
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对一查询 用法参考 selectCollection
|
||||||
|
*
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
default <S, C, F> Children selectAssociation(BaseColumn<C> child, SFunction<S, F> dtoField) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||||
|
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||||
|
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||||
|
FieldCache field = fieldMap.get(dtoFieldName);
|
||||||
|
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||||
|
MybatisLabel.Builder<C, F> builder;
|
||||||
|
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<F>) field.getType(), true);
|
||||||
|
addLabel(builder.build());
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, C, F> Children selectAssociation(SFunction<S, F> dtoField,
|
||||||
|
MFunction<MybatisLabelFree.Builder<F>> collection) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||||
|
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||||
|
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||||
|
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||||
|
MybatisLabelFree.Builder<F> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), (Class<F>) field.getType());
|
||||||
|
MybatisLabelFree.Builder<F> cfBuilder = collection.apply(builder);
|
||||||
|
addLabel(cfBuilder.build());
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S, C, F> Children selectAssociation(BaseColumn<C> child, SFunction<S, F> dtoField,
|
||||||
|
MFunction<MybatisLabel.Builder<C, F>> collection) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||||
|
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||||
|
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||||
|
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||||
|
MybatisLabel.Builder<C, F> builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<F>) field.getType(), false);
|
||||||
|
MybatisLabel.Builder<C, F> cfBuilder = collection.apply(builder);
|
||||||
|
addLabel(cfBuilder.build());
|
||||||
|
return getChildren();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,275 @@
|
|||||||
|
package com.github.yulichang.wrapper.apt.resultmap;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
import com.github.yulichang.toolkit.LambdaUtils;
|
||||||
|
import com.github.yulichang.toolkit.MPJReflectionKit;
|
||||||
|
import com.github.yulichang.toolkit.TableHelper;
|
||||||
|
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||||
|
import com.github.yulichang.toolkit.support.FieldCache;
|
||||||
|
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||||
|
import com.github.yulichang.wrapper.resultmap.IResult;
|
||||||
|
import com.github.yulichang.wrapper.resultmap.Label;
|
||||||
|
import com.github.yulichang.wrapper.segments.SelectCache;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* collection 标签 目前先支持这几个属性 后续在扩展
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public class MybatisLabel<E, T> implements Label<T> {
|
||||||
|
|
||||||
|
private String property;
|
||||||
|
|
||||||
|
private BaseColumn<E> baseColumn;
|
||||||
|
|
||||||
|
private Class<?> javaType;
|
||||||
|
|
||||||
|
private Class<T> ofType;
|
||||||
|
|
||||||
|
private List<IResult> resultList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wrapper里面的引用
|
||||||
|
*/
|
||||||
|
private List<Label<?>> mybatisLabels;
|
||||||
|
|
||||||
|
private MybatisLabel() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "unchecked", "DuplicatedCode"})
|
||||||
|
public static class Builder<E, T> {
|
||||||
|
|
||||||
|
private final MybatisLabel<E, T> mybatisLabel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动构建
|
||||||
|
*/
|
||||||
|
public Builder(String property, BaseColumn<E> baseColumn, Class<?> javaType) {
|
||||||
|
this.mybatisLabel = new MybatisLabel<>();
|
||||||
|
mybatisLabel.property = property;
|
||||||
|
mybatisLabel.baseColumn = baseColumn;
|
||||||
|
mybatisLabel.javaType = javaType;
|
||||||
|
mybatisLabel.ofType = (Class<T>) baseColumn.getColumnClass();
|
||||||
|
mybatisLabel.resultList = new ArrayList<>();
|
||||||
|
mybatisLabel.mybatisLabels = new ArrayList<>();
|
||||||
|
autoBuild(true, baseColumn.getColumnClass(), (Class<T>) baseColumn.getColumnClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手动构建
|
||||||
|
*
|
||||||
|
* @param property property
|
||||||
|
* @param baseColumn 数据库实体类
|
||||||
|
* @param javaType javaType
|
||||||
|
* @param ofType 映射类
|
||||||
|
* @param auto 自动映射数据库实体对应的字段
|
||||||
|
*/
|
||||||
|
public Builder(String property, BaseColumn<E> baseColumn, Class<?> javaType, Class<T> ofType, boolean auto) {
|
||||||
|
this.mybatisLabel = new MybatisLabel<>();
|
||||||
|
mybatisLabel.property = property;
|
||||||
|
mybatisLabel.baseColumn = baseColumn;
|
||||||
|
mybatisLabel.javaType = javaType;
|
||||||
|
mybatisLabel.ofType = ofType;
|
||||||
|
mybatisLabel.resultList = new ArrayList<>();
|
||||||
|
mybatisLabel.mybatisLabels = new ArrayList<>();
|
||||||
|
autoBuild(auto, baseColumn.getColumnClass(), ofType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射实体全部字段
|
||||||
|
*/
|
||||||
|
public Builder<E, T> all() {
|
||||||
|
autoBuild(true, mybatisLabel.baseColumn.getColumnClass(), mybatisLabel.ofType);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射实体字段过滤(含主键)
|
||||||
|
*/
|
||||||
|
public Builder<E, T> filter(Predicate<SelectCache> predicate) {
|
||||||
|
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(mybatisLabel.ofType);
|
||||||
|
ColumnCache.getListField(mybatisLabel.baseColumn.getColumnClass()).stream().filter(predicate)
|
||||||
|
.filter(p -> fieldMap.containsKey(p.getColumProperty())).forEach(c ->
|
||||||
|
mybatisLabel.resultList.add(new Result.Builder<T>(c.isPk(), mybatisLabel.baseColumn, c).build()));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<E, T> id(Column column, SFunction<T, ?> tag) {
|
||||||
|
Result.Builder<T> builder = new Result.Builder<>(true, column);
|
||||||
|
builder.column(column).property(tag);
|
||||||
|
mybatisLabel.resultList.add(builder.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<E, T> id(Column column) {
|
||||||
|
Result.Builder<T> builder = new Result.Builder<>(true, column);
|
||||||
|
builder.column(column);
|
||||||
|
mybatisLabel.resultList.add(builder.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<E, T> result(Column column, SFunction<T, ?> tag) {
|
||||||
|
Result.Builder<T> builder = new Result.Builder<>(false, column);
|
||||||
|
builder.column(column).property(tag);
|
||||||
|
mybatisLabel.resultList.add(builder.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<E, T> result(Column column) {
|
||||||
|
Result.Builder<T> builder = new Result.Builder<>(false, column);
|
||||||
|
builder.column(column);
|
||||||
|
mybatisLabel.resultList.add(builder.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 嵌套
|
||||||
|
*/
|
||||||
|
public <A, R, B extends Collection<R>> Builder<E, T> collection(BaseColumn<A> entityClass, SFunction<T, B> func) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(func);
|
||||||
|
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||||
|
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||||
|
FieldCache field = fieldMap.get(dtoFieldName);
|
||||||
|
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||||
|
Builder<A, R> builder;
|
||||||
|
if (genericType == null || genericType.isAssignableFrom(entityClass.getColumnClass())) {
|
||||||
|
//找不到集合泛型 List List<?> List<Object> , 直接查询数据库实体
|
||||||
|
builder = new Builder<>(dtoFieldName, entityClass, field.getType());
|
||||||
|
} else {
|
||||||
|
Class<R> ofType = (Class<R>) genericType;
|
||||||
|
builder = new Builder<>(dtoFieldName, entityClass, field.getType(), ofType, true);
|
||||||
|
}
|
||||||
|
mybatisLabel.mybatisLabels.add(builder.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 嵌套
|
||||||
|
*/
|
||||||
|
public <A, R, B extends Collection<R>> Builder<E, T> collection(SFunction<T, B> func,
|
||||||
|
MFunction<MybatisLabelFree.Builder<R>> mFunc) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(func);
|
||||||
|
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||||
|
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||||
|
//获取集合泛型
|
||||||
|
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||||
|
Class<R> ofType = (Class<R>) genericType;
|
||||||
|
MybatisLabelFree.Builder<R> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), ofType);
|
||||||
|
mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 嵌套
|
||||||
|
*/
|
||||||
|
public <A, R, B extends Collection<R>> Builder<E, T> collection(BaseColumn<A> entityClass,
|
||||||
|
SFunction<T, B> func,
|
||||||
|
MFunction<Builder<A, R>> mFunc) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(func);
|
||||||
|
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||||
|
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||||
|
//获取集合泛型
|
||||||
|
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||||
|
Class<R> ofType = (Class<R>) genericType;
|
||||||
|
Builder<A, R> builder = new Builder<>(dtoFieldName, entityClass, field.getType(), ofType, false);
|
||||||
|
mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 嵌套
|
||||||
|
*/
|
||||||
|
public <A, B> Builder<E, T> association(BaseColumn<A> child, SFunction<T, B> dtoField) {
|
||||||
|
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||||
|
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||||
|
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||||
|
FieldCache field = fieldMap.get(dtoFieldName);
|
||||||
|
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||||
|
Builder<A, B> builder;
|
||||||
|
builder = new Builder<>(dtoFieldName, child, field.getType(), (Class<B>) field.getType(), true);
|
||||||
|
mybatisLabel.mybatisLabels.add(builder.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 嵌套
|
||||||
|
*/
|
||||||
|
public <A, B> Builder<E, T> association(SFunction<T, B> dtoField,
|
||||||
|
MFunction<MybatisLabelFree.Builder<B>> collection) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||||
|
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||||
|
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||||
|
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||||
|
MybatisLabelFree.Builder<B> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), (Class<B>) field.getType());
|
||||||
|
mybatisLabel.mybatisLabels.add(collection.apply(builder).build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 嵌套
|
||||||
|
*/
|
||||||
|
public <A, B> Builder<E, T> association(BaseColumn<A> child, SFunction<T, B> dtoField,
|
||||||
|
MFunction<Builder<A, B>> collection) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||||
|
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||||
|
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||||
|
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||||
|
Builder<A, B> builder = new Builder<>(dtoFieldName, child, field.getType(), (Class<B>) field.getType(), false);
|
||||||
|
mybatisLabel.mybatisLabels.add(collection.apply(builder).build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MybatisLabel<E, T> build() {
|
||||||
|
if (CollectionUtils.isEmpty(mybatisLabel.resultList)) {
|
||||||
|
autoBuild(true, mybatisLabel.baseColumn.getColumnClass(), mybatisLabel.ofType);
|
||||||
|
}
|
||||||
|
return mybatisLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void autoBuild(boolean auto, Class<E> entityClass, Class<T> tagClass) {
|
||||||
|
TableInfo tableInfo = TableHelper.getAssert(entityClass);
|
||||||
|
Map<String, FieldCache> tagMap = MPJReflectionKit.getFieldMap(tagClass);
|
||||||
|
if (auto && !tagMap.isEmpty()) {
|
||||||
|
List<SelectCache> listField = ColumnCache.getListField(entityClass);
|
||||||
|
if (entityClass.isAssignableFrom(tagClass)) {
|
||||||
|
mybatisLabel.resultList.addAll(listField.stream().map(i -> {
|
||||||
|
Result result = new Result();
|
||||||
|
result.setId(i.isPk());
|
||||||
|
result.setBaseColumn(mybatisLabel.baseColumn);
|
||||||
|
result.setProperty(i.getColumProperty());
|
||||||
|
result.setJavaType(i.getColumnType());
|
||||||
|
result.setJdbcType(Objects.isNull(i.getTableFieldInfo()) ? null : i.getTableFieldInfo().getJdbcType());
|
||||||
|
result.setSelectNormal(i);
|
||||||
|
return result;
|
||||||
|
}).collect(Collectors.toList()));
|
||||||
|
} else {
|
||||||
|
for (SelectCache s : listField) {
|
||||||
|
FieldCache field = tagMap.get(s.getColumProperty());
|
||||||
|
if (Objects.nonNull(field)) {
|
||||||
|
Result result = new Result();
|
||||||
|
result.setId(s.isPk());
|
||||||
|
result.setBaseColumn(mybatisLabel.baseColumn);
|
||||||
|
result.setProperty(s.getColumProperty());
|
||||||
|
result.setJavaType(field.getType());
|
||||||
|
result.setSelectNormal(s);
|
||||||
|
mybatisLabel.resultList.add(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,220 @@
|
|||||||
|
package com.github.yulichang.wrapper.apt.resultmap;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
import com.github.yulichang.toolkit.LambdaUtils;
|
||||||
|
import com.github.yulichang.toolkit.MPJReflectionKit;
|
||||||
|
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||||
|
import com.github.yulichang.toolkit.support.FieldCache;
|
||||||
|
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||||
|
import com.github.yulichang.wrapper.resultmap.IResult;
|
||||||
|
import com.github.yulichang.wrapper.resultmap.Label;
|
||||||
|
import com.github.yulichang.wrapper.resultmap.ResultList;
|
||||||
|
import com.github.yulichang.wrapper.segments.SelectCache;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 无泛型约束 实现自由映射
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.4.4
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public class MybatisLabelFree<T> implements Label<T> {
|
||||||
|
|
||||||
|
private String property;
|
||||||
|
|
||||||
|
private Class<?> javaType;
|
||||||
|
|
||||||
|
private Class<T> ofType;
|
||||||
|
|
||||||
|
private List<IResult> resultList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wrapper里面的引用
|
||||||
|
*/
|
||||||
|
private List<Label<?>> mybatisLabels;
|
||||||
|
|
||||||
|
private MybatisLabelFree() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "unchecked", "DuplicatedCode"})
|
||||||
|
public static class Builder<T> {
|
||||||
|
|
||||||
|
private final MybatisLabelFree<T> mybatisLabel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手动构建
|
||||||
|
*
|
||||||
|
* @param property property
|
||||||
|
* @param javaType javaType
|
||||||
|
* @param ofType 映射类
|
||||||
|
*/
|
||||||
|
public Builder(String property, Class<?> javaType, Class<T> ofType) {
|
||||||
|
this.mybatisLabel = new MybatisLabelFree<>();
|
||||||
|
mybatisLabel.property = property;
|
||||||
|
mybatisLabel.javaType = javaType;
|
||||||
|
mybatisLabel.ofType = ofType;
|
||||||
|
mybatisLabel.resultList = new ResultList();
|
||||||
|
mybatisLabel.mybatisLabels = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public <E> Builder<T> all(BaseColumn<E> entityClass) {
|
||||||
|
allBuild(entityClass);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射实体字段过滤(含主键)
|
||||||
|
*/
|
||||||
|
public <E> Builder<T> filter(BaseColumn<E> baseColumn, Predicate<SelectCache> predicate) {
|
||||||
|
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(mybatisLabel.ofType);
|
||||||
|
ColumnCache.getListField(baseColumn.getColumnClass()).stream().filter(predicate)
|
||||||
|
.filter(p -> fieldMap.containsKey(p.getColumProperty())).forEach(c ->
|
||||||
|
mybatisLabel.resultList.add(new Result.Builder<T>(false, baseColumn, c).build()));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<T> id(Column column, SFunction<T, ?> tag) {
|
||||||
|
Result.Builder<T> builder = new Result.Builder<>(true, column);
|
||||||
|
builder.column(column).property(tag);
|
||||||
|
mybatisLabel.resultList.add(builder.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<T> id(Column column) {
|
||||||
|
Result.Builder<T> builder = new Result.Builder<>(true, column);
|
||||||
|
builder.column(column);
|
||||||
|
mybatisLabel.resultList.add(builder.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<T> result(Column column, SFunction<T, ?> tag) {
|
||||||
|
Result.Builder<T> builder = new Result.Builder<>(false, column);
|
||||||
|
builder.column(column).property(tag);
|
||||||
|
mybatisLabel.resultList.add(builder.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<T> result(Column column) {
|
||||||
|
Result.Builder<T> builder = new Result.Builder<>(false, column);
|
||||||
|
builder.column(column);
|
||||||
|
mybatisLabel.resultList.add(builder.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 嵌套
|
||||||
|
*/
|
||||||
|
public <A, R, B extends Collection<R>> Builder<T> collection(BaseColumn<A> baseColumn, SFunction<T, B> func) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(func);
|
||||||
|
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||||
|
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||||
|
FieldCache field = fieldMap.get(dtoFieldName);
|
||||||
|
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||||
|
MybatisLabel.Builder<A, R> builder;
|
||||||
|
if (genericType == null || genericType.isAssignableFrom(baseColumn.getColumnClass())) {
|
||||||
|
//找不到集合泛型 List List<?> List<Object> , 直接查询数据库实体
|
||||||
|
builder = new MybatisLabel.Builder<>(dtoFieldName, baseColumn, field.getType());
|
||||||
|
} else {
|
||||||
|
Class<R> ofType = (Class<R>) genericType;
|
||||||
|
builder = new MybatisLabel.Builder<>(dtoFieldName, baseColumn, field.getType(), ofType, true);
|
||||||
|
}
|
||||||
|
mybatisLabel.mybatisLabels.add(builder.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <A, R, B extends Collection<R>> Builder<T> collection(SFunction<T, B> func,
|
||||||
|
MFunction<Builder<R>> mFunc) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(func);
|
||||||
|
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||||
|
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||||
|
//获取集合泛型
|
||||||
|
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||||
|
Class<R> ofType = (Class<R>) genericType;
|
||||||
|
Builder<R> builder = new Builder<>(dtoFieldName, field.getType(), ofType);
|
||||||
|
mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 嵌套
|
||||||
|
*/
|
||||||
|
public <A, R, B extends Collection<R>> Builder<T> collection(BaseColumn<A> entityClass,
|
||||||
|
SFunction<T, B> func,
|
||||||
|
MFunction<MybatisLabel.Builder<A, R>> mFunc) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(func);
|
||||||
|
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||||
|
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||||
|
//获取集合泛型
|
||||||
|
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||||
|
Class<R> ofType = (Class<R>) genericType;
|
||||||
|
MybatisLabel.Builder<A, R> builder = new MybatisLabel.Builder<>(dtoFieldName, entityClass, field.getType(), ofType, false);
|
||||||
|
mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 嵌套
|
||||||
|
*/
|
||||||
|
public <A, B> Builder<T> association(BaseColumn<A> child, SFunction<T, B> dtoField) {
|
||||||
|
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||||
|
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||||
|
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||||
|
FieldCache field = fieldMap.get(dtoFieldName);
|
||||||
|
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||||
|
MybatisLabel.Builder<A, B> builder;
|
||||||
|
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<B>) field.getType(), true);
|
||||||
|
mybatisLabel.mybatisLabels.add(builder.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 嵌套
|
||||||
|
*/
|
||||||
|
public <A, B> Builder<T> association(BaseColumn<A> child, SFunction<T, B> dtoField,
|
||||||
|
MFunction<MybatisLabel.Builder<A, B>> collection) {
|
||||||
|
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||||
|
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||||
|
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||||
|
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||||
|
MybatisLabel.Builder<A, B> builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<B>) field.getType(), false);
|
||||||
|
mybatisLabel.mybatisLabels.add(collection.apply(builder).build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MybatisLabelFree<T> build() {
|
||||||
|
if (CollectionUtils.isEmpty(mybatisLabel.resultList)) {
|
||||||
|
throw ExceptionUtils.mpe("无法自动映射, 找不到 <%s> 对应的表, 请使用 .all(xxx.class), id()或者result() 手动映射",
|
||||||
|
mybatisLabel.ofType.getSimpleName());
|
||||||
|
}
|
||||||
|
return mybatisLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void allBuild(BaseColumn<?> entityClass) {
|
||||||
|
Map<String, FieldCache> tagMap = MPJReflectionKit.getFieldMap(mybatisLabel.getOfType());
|
||||||
|
List<SelectCache> listField = ColumnCache.getListField(entityClass.getColumnClass());
|
||||||
|
for (SelectCache s : listField) {
|
||||||
|
FieldCache field = tagMap.get(s.getColumProperty());
|
||||||
|
if (Objects.nonNull(field)) {
|
||||||
|
Result result = new Result();
|
||||||
|
result.setBaseColumn(entityClass);
|
||||||
|
result.setId(s.isPk());
|
||||||
|
result.setJavaType(field.getType());
|
||||||
|
result.setProperty(s.getColumProperty());
|
||||||
|
result.setSelectNormal(s);
|
||||||
|
mybatisLabel.resultList.add(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,125 @@
|
|||||||
|
package com.github.yulichang.wrapper.apt.resultmap;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
import com.github.yulichang.toolkit.LambdaUtils;
|
||||||
|
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||||
|
import com.github.yulichang.wrapper.resultmap.IResult;
|
||||||
|
import com.github.yulichang.wrapper.segments.SelectCache;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.ibatis.type.JdbcType;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* result 标签
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter(AccessLevel.PACKAGE)
|
||||||
|
public class Result implements IResult {
|
||||||
|
|
||||||
|
private boolean isId;
|
||||||
|
|
||||||
|
private BaseColumn<?> baseColumn;
|
||||||
|
|
||||||
|
private Column column;
|
||||||
|
|
||||||
|
private SelectCache selectNormal;
|
||||||
|
|
||||||
|
private String property;
|
||||||
|
|
||||||
|
private Class<?> javaType;
|
||||||
|
|
||||||
|
private JdbcType jdbcType;
|
||||||
|
|
||||||
|
public Result() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIndex() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings({"UnusedReturnValue", "unused"})
|
||||||
|
public static class Builder<T> {
|
||||||
|
|
||||||
|
private final Result result;
|
||||||
|
|
||||||
|
public Builder(boolean isId, Column column) {
|
||||||
|
this.result = new Result();
|
||||||
|
result.isId = isId;
|
||||||
|
result.column = column;
|
||||||
|
result.baseColumn = column.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder(boolean isId, Column column, SelectCache selectCache) {
|
||||||
|
this.result = new Result();
|
||||||
|
result.isId = isId;
|
||||||
|
result.column = column;
|
||||||
|
result.baseColumn = column.getRoot();
|
||||||
|
result.selectNormal = selectCache;
|
||||||
|
result.property = selectCache.getColumProperty();
|
||||||
|
result.javaType = selectCache.getColumnType();
|
||||||
|
result.jdbcType = Optional.ofNullable(selectCache.getTableFieldInfo()).map(TableFieldInfo::getJdbcType).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder(boolean isId, BaseColumn<?> baseColumn, SelectCache selectCache) {
|
||||||
|
this.result = new Result();
|
||||||
|
result.isId = isId;
|
||||||
|
result.column = null;
|
||||||
|
result.baseColumn = baseColumn;
|
||||||
|
result.selectNormal = selectCache;
|
||||||
|
result.property = selectCache.getColumProperty();
|
||||||
|
result.javaType = selectCache.getColumnType();
|
||||||
|
result.jdbcType = Optional.ofNullable(selectCache.getTableFieldInfo()).map(TableFieldInfo::getJdbcType).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<T> property(SFunction<T, ?> property) {
|
||||||
|
result.property = LambdaUtils.getName(property);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<T> column(Column column) {
|
||||||
|
Map<String, SelectCache> normalMap = ColumnCache.getMapField(column.getClazz());
|
||||||
|
SelectCache normal = normalMap.get(column.getProperty());
|
||||||
|
result.selectNormal = normal;
|
||||||
|
result.column = column;
|
||||||
|
if (StringUtils.isBlank(result.property)) {
|
||||||
|
result.property = normal.getColumProperty();
|
||||||
|
}
|
||||||
|
if (Objects.isNull(result.javaType)) {
|
||||||
|
result.javaType = normal.getColumnType();
|
||||||
|
}
|
||||||
|
if (Objects.isNull(result.jdbcType)) {
|
||||||
|
result.jdbcType = Objects.isNull(normal.getTableFieldInfo()) ? null : normal.getTableFieldInfo().getJdbcType();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<T> javaType(Class<?> javaType) {
|
||||||
|
result.javaType = javaType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<T> jdbcType(JdbcType jdbcType) {
|
||||||
|
result.jdbcType = jdbcType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result build() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package com.github.yulichang.wrapper.interfaces;
|
package com.github.yulichang.wrapper.interfaces;
|
||||||
|
|
||||||
|
import com.github.yulichang.wrapper.resultmap.Label;
|
||||||
import com.github.yulichang.wrapper.segments.Select;
|
import com.github.yulichang.wrapper.segments.Select;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -16,11 +17,11 @@ public interface SelectWrapper<Entity, Children> {
|
|||||||
|
|
||||||
List<Select> getSelectColumns();
|
List<Select> getSelectColumns();
|
||||||
|
|
||||||
Children selectAll(Class<?> clazz);
|
Children selectAll();
|
||||||
|
|
||||||
boolean isResultMap();
|
boolean isResultMap();
|
||||||
|
|
||||||
List<?> getResultMapMybatisLabel();
|
List<Label<?>> getResultMapMybatisLabel();
|
||||||
|
|
||||||
String getFrom();
|
String getFrom();
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.github.yulichang.wrapper.resultmap;
|
package com.github.yulichang.wrapper.resultmap;
|
||||||
|
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
import com.github.yulichang.wrapper.segments.SelectCache;
|
import com.github.yulichang.wrapper.segments.SelectCache;
|
||||||
import org.apache.ibatis.type.JdbcType;
|
import org.apache.ibatis.type.JdbcType;
|
||||||
|
|
||||||
@ -16,4 +17,8 @@ public interface IResult {
|
|||||||
Class<?> getJavaType();
|
Class<?> getJavaType();
|
||||||
|
|
||||||
JdbcType getJdbcType();
|
JdbcType getJdbcType();
|
||||||
|
|
||||||
|
default BaseColumn<?> getBaseColumn() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.github.yulichang.wrapper.segments;
|
||||||
|
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于selectFunc 和 applyFunc中的参数填充
|
||||||
|
* 从原来的 {@link SelectFunc} 里的内部类中提取出来
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.4.13
|
||||||
|
*/
|
||||||
|
public class AptConsumer {
|
||||||
|
|
||||||
|
public static final AptConsumer func = new AptConsumer();
|
||||||
|
|
||||||
|
public final Column[] accept(Column... a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package com.github.yulichang.wrapper.segments;
|
package com.github.yulichang.wrapper.segments;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
||||||
import org.apache.ibatis.type.TypeHandler;
|
import org.apache.ibatis.type.TypeHandler;
|
||||||
|
|
||||||
@ -51,4 +53,12 @@ public interface Select extends Serializable {
|
|||||||
boolean isLabel();
|
boolean isLabel();
|
||||||
|
|
||||||
boolean isStr();
|
boolean isStr();
|
||||||
|
|
||||||
|
default Column[] getColumns() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default BaseColumn<?> getBaseColumn() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,228 @@
|
|||||||
|
package com.github.yulichang.wrapper.segments;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.ibatis.type.TypeHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存列
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.5.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SelectApt implements Select {
|
||||||
|
|
||||||
|
private final SelectCache cache;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private BaseColumn<?> baseColumn;
|
||||||
|
|
||||||
|
private final boolean isFunc;
|
||||||
|
|
||||||
|
private final BaseFuncEnum func;
|
||||||
|
|
||||||
|
private final boolean hasAlias;
|
||||||
|
|
||||||
|
private final String alias;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final Column[] columns;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* select(col)
|
||||||
|
*/
|
||||||
|
public SelectApt(SelectCache cache, Column column) {
|
||||||
|
this.cache = cache;
|
||||||
|
this.baseColumn = column.getRoot();
|
||||||
|
this.isFunc = false;
|
||||||
|
this.func = null;
|
||||||
|
this.columns = null;
|
||||||
|
this.hasAlias = false;
|
||||||
|
this.alias = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* select(col)
|
||||||
|
*/
|
||||||
|
public SelectApt(SelectCache cache, BaseColumn<?> baseColumn) {
|
||||||
|
this.cache = cache;
|
||||||
|
this.baseColumn = baseColumn;
|
||||||
|
this.isFunc = false;
|
||||||
|
this.func = null;
|
||||||
|
this.columns = null;
|
||||||
|
this.hasAlias = false;
|
||||||
|
this.alias = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* selectAs(col,alias)
|
||||||
|
*/
|
||||||
|
public SelectApt(SelectCache cache, Column column, String alias) {
|
||||||
|
this.cache = cache;
|
||||||
|
this.baseColumn = column.getRoot();
|
||||||
|
this.isFunc = false;
|
||||||
|
this.func = null;
|
||||||
|
this.columns = null;
|
||||||
|
this.hasAlias = true;
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* select(()->"", col)
|
||||||
|
*/
|
||||||
|
public SelectApt(SelectCache cache, Column column, BaseFuncEnum baseFuncEnum, String alias) {
|
||||||
|
this.cache = cache;
|
||||||
|
this.baseColumn = column.getRoot();
|
||||||
|
this.isFunc = true;
|
||||||
|
this.func = baseFuncEnum;
|
||||||
|
this.columns = new Column[]{column};
|
||||||
|
this.hasAlias = true;
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* select("", arg.accept(col...))
|
||||||
|
*/
|
||||||
|
public SelectApt(Column[] columns, BaseFuncEnum baseFuncEnum, String alias) {
|
||||||
|
this.cache = null;
|
||||||
|
this.baseColumn = null;
|
||||||
|
this.isFunc = true;
|
||||||
|
this.func = baseFuncEnum;
|
||||||
|
this.columns = columns;
|
||||||
|
this.hasAlias = true;
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isHasTableAlias() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTableAlias() {
|
||||||
|
if (baseColumn != null) {
|
||||||
|
return baseColumn.getAlias();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getClazz() {
|
||||||
|
if (cache != null) {
|
||||||
|
return cache.getClazz();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getIndex() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPk() {
|
||||||
|
if (cache != null) {
|
||||||
|
return cache.isPk();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getColumn() {
|
||||||
|
if (cache != null) {
|
||||||
|
return cache.getColumn();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getColumnType() {
|
||||||
|
if (cache != null) {
|
||||||
|
return cache.getColumnType();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTagColumn() {
|
||||||
|
if (cache != null) {
|
||||||
|
return cache.getTagColumn();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getColumProperty() {
|
||||||
|
if (cache != null) {
|
||||||
|
return cache.getColumProperty();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasTypeHandle() {
|
||||||
|
if (cache != null) {
|
||||||
|
return cache.isHasTypeHandle();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeHandler<?> getTypeHandle() {
|
||||||
|
if (cache != null) {
|
||||||
|
return cache.getTypeHandler();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isHasAlias() {
|
||||||
|
return this.hasAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAlias() {
|
||||||
|
return this.alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableFieldInfo getTableFieldInfo() {
|
||||||
|
if (cache != null) {
|
||||||
|
return cache.getTableFieldInfo();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFunc() {
|
||||||
|
return this.isFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SelectFunc.Arg[] getArgs() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseFuncEnum getFunc() {
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLabel() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStr() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package com.github.yulichang.wrapper.segments;
|
|||||||
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.apache.ibatis.type.TypeHandler;
|
import org.apache.ibatis.type.TypeHandler;
|
||||||
@ -29,24 +30,28 @@ public class SelectLabel implements Select {
|
|||||||
|
|
||||||
private final String tableAlias;
|
private final String tableAlias;
|
||||||
|
|
||||||
public SelectLabel(SelectCache cache, Integer index, Class<?> tagClass, boolean hasTableAlias, String tableAlias) {
|
private final BaseColumn<?> baseColumn;
|
||||||
|
|
||||||
|
public SelectLabel(SelectCache cache, Integer index, Class<?> tagClass, boolean hasTableAlias, String tableAlias, BaseColumn<?> baseColumn) {
|
||||||
this.cache = cache;
|
this.cache = cache;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.tagClass = tagClass;
|
this.tagClass = tagClass;
|
||||||
this.hasAlias = false;
|
this.hasAlias = false;
|
||||||
this.alias = null;
|
this.alias = null;
|
||||||
this.hasTableAlias = hasTableAlias;
|
this.hasTableAlias = hasTableAlias;
|
||||||
this.tableAlias = tableAlias;
|
this.tableAlias = hasTableAlias ? tableAlias : null;
|
||||||
|
this.baseColumn = baseColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SelectLabel(SelectCache cache, Integer index, Class<?> tagClass, String column, boolean hasTableAlias, String tableAlias) {
|
public SelectLabel(SelectCache cache, Integer index, Class<?> tagClass, String column, boolean hasTableAlias, String tableAlias, BaseColumn<?> baseColumn) {
|
||||||
this.cache = cache;
|
this.cache = cache;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.tagClass = tagClass;
|
this.tagClass = tagClass;
|
||||||
this.hasAlias = true;
|
this.hasAlias = true;
|
||||||
this.alias = column;
|
this.alias = column;
|
||||||
this.hasTableAlias = hasTableAlias;
|
this.hasTableAlias = hasTableAlias;
|
||||||
this.tableAlias = tableAlias;
|
this.tableAlias = hasTableAlias ? tableAlias : null;
|
||||||
|
this.baseColumn = baseColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
70
mybatis-plus-join-processor/pom.xml
Normal file
70
mybatis-plus-join-processor/pom.xml
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.github.yulichang</groupId>
|
||||||
|
<artifactId>mybatis-plus-join-root</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>mybatis-plus-join-processor</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.yulichang</groupId>
|
||||||
|
<artifactId>mybatis-plus-join-core</artifactId>
|
||||||
|
<version>1.4.13</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-annotation</artifactId>
|
||||||
|
<version>${mpj.mybatis.plus.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis</groupId>
|
||||||
|
<artifactId>mybatis</artifactId>
|
||||||
|
<version>3.5.16</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*</include>
|
||||||
|
</includes>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
*.properties
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>target/generated-sources</directory>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<proc>none</proc>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,266 @@
|
|||||||
|
package com.github.yulichang.processor;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.github.yulichang.annotation.Table;
|
||||||
|
import com.github.yulichang.apt.BaseColumn;
|
||||||
|
import com.github.yulichang.apt.Column;
|
||||||
|
import com.github.yulichang.processor.matedata.FieldInfo;
|
||||||
|
import com.github.yulichang.processor.matedata.TableInfo;
|
||||||
|
import com.github.yulichang.processor.utils.StringUtil;
|
||||||
|
|
||||||
|
import javax.annotation.processing.AbstractProcessor;
|
||||||
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
|
import javax.annotation.processing.RoundEnvironment;
|
||||||
|
import javax.lang.model.SourceVersion;
|
||||||
|
import javax.lang.model.element.ElementKind;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.lang.model.util.Elements;
|
||||||
|
import javax.lang.model.util.Types;
|
||||||
|
import javax.tools.Diagnostic;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.5.0
|
||||||
|
*/
|
||||||
|
public class EntityProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
|
private Elements elementUtils;
|
||||||
|
private Types typeUtils;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void init(ProcessingEnvironment processingEnv) {
|
||||||
|
super.init(processingEnv);
|
||||||
|
this.elementUtils = processingEnv.getElementUtils();
|
||||||
|
this.typeUtils = processingEnv.getTypeUtils();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||||
|
if (!roundEnv.processingOver()) {
|
||||||
|
roundEnv.getElementsAnnotatedWith(Table.class).stream().filter(f -> f instanceof TypeElement)
|
||||||
|
.map(f -> (TypeElement) f).map(this::createColumn)
|
||||||
|
.collect(Collectors.groupingBy(TableInfo::getClassPackage))
|
||||||
|
.forEach(this::createTables);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getSupportedAnnotationTypes() {
|
||||||
|
Set<String> supportedAnnotationTypes = new HashSet<>();
|
||||||
|
supportedAnnotationTypes.add(Table.class.getCanonicalName());
|
||||||
|
return supportedAnnotationTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceVersion getSupportedSourceVersion() {
|
||||||
|
return SourceVersion.latestSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成Column类
|
||||||
|
*/
|
||||||
|
private TableInfo createColumn(TypeElement element) {
|
||||||
|
TableInfo tableInfo = new TableInfo(element.getAnnotation(Table.class));
|
||||||
|
tableInfo.setClassName(element.toString());
|
||||||
|
tableInfo.setSimpleClassName(element.getSimpleName().toString());
|
||||||
|
tableInfo.setClassPackage(elementUtils.getPackageOf(element).getQualifiedName().toString());
|
||||||
|
tableInfo.setClassComment(elementUtils.getDocComment(element));
|
||||||
|
|
||||||
|
Set<FieldInfo> fieldInfos = new HashSet<>();
|
||||||
|
|
||||||
|
TypeElement currElement = element;
|
||||||
|
do {
|
||||||
|
fieldInfos.addAll(currElement.getEnclosedElements().stream().filter(e ->
|
||||||
|
// 过滤static字段
|
||||||
|
e.getKind() == ElementKind.FIELD && !e.getModifiers().contains(Modifier.STATIC))
|
||||||
|
.filter(e -> {
|
||||||
|
// 过滤 exist = false 的字段
|
||||||
|
TableField tableField = e.getAnnotation(TableField.class);
|
||||||
|
return tableField == null || tableField.exist();
|
||||||
|
})
|
||||||
|
.map(e -> new FieldInfo(e.toString(), elementUtils.getDocComment(e))).collect(Collectors.toList()));
|
||||||
|
currElement = (TypeElement) typeUtils.asElement(currElement.getSuperclass());
|
||||||
|
} while (currElement != null);
|
||||||
|
|
||||||
|
tableInfo.setFields(fieldInfos);
|
||||||
|
|
||||||
|
StringBuilderHelper content = new StringBuilderHelper()
|
||||||
|
.addPackage(tableInfo.getTagPackage())
|
||||||
|
.newLine()
|
||||||
|
.addImport(BaseColumn.class.getName())
|
||||||
|
.addImport(Column.class.getName())
|
||||||
|
.addImport(tableInfo.getClassName())
|
||||||
|
.newLine()
|
||||||
|
.addClass(tableInfo.getClassComment(), tableInfo.getTagClassName(),
|
||||||
|
BaseColumn.class.getSimpleName() + "<" + tableInfo.getSimpleClassName() + ">",
|
||||||
|
c -> c
|
||||||
|
.addDefaultField(tableInfo.getSimpleClassName())
|
||||||
|
.addConstructor(tableInfo)
|
||||||
|
.addFields(tableInfo)
|
||||||
|
.addMethod(tableInfo)
|
||||||
|
);
|
||||||
|
writerFile(tableInfo.getTagPackage() + "." + tableInfo.getTagClassName(), content.getContent());
|
||||||
|
return tableInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成Tables
|
||||||
|
*/
|
||||||
|
private void createTables(String tagPackage, List<TableInfo> tableInfos) {
|
||||||
|
StringBuilderHelper content = new StringBuilderHelper();
|
||||||
|
// package
|
||||||
|
content.addPackage(tagPackage + ".tables");
|
||||||
|
content.newLine();
|
||||||
|
// import
|
||||||
|
tableInfos.forEach(tableInfo -> content.addImport(tableInfo.getTagPackage() + "." + tableInfo.getTagClassName()));
|
||||||
|
content.newLine();
|
||||||
|
// class
|
||||||
|
String tables = "Tables";
|
||||||
|
content.addClass(" tables", tables, "", c -> c
|
||||||
|
.newLine()
|
||||||
|
// 私有构造
|
||||||
|
.addPrivateConstructor(tables)
|
||||||
|
// 添加table字段
|
||||||
|
.addTablesFields(tableInfos));
|
||||||
|
|
||||||
|
writerFile(tagPackage + ".tables.Tables", content.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writerFile(String fullClassName, String content) {
|
||||||
|
try {
|
||||||
|
JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(fullClassName);
|
||||||
|
|
||||||
|
Writer writer = sourceFile.openWriter();
|
||||||
|
writer.write(content);
|
||||||
|
writer.flush();
|
||||||
|
writer.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("UnusedReturnValue")
|
||||||
|
public static class StringBuilderHelper {
|
||||||
|
private final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
public StringBuilderHelper addPackage(String packageName) {
|
||||||
|
sb.append("package ").append(packageName).append(";\n");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuilderHelper addImport(String importName) {
|
||||||
|
sb.append("import ").append(importName).append(";\n");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuilderHelper addClass(String comment, String tagClassName, String impl,
|
||||||
|
Consumer<StringBuilderHelper> consumer) {
|
||||||
|
addComment("", comment);
|
||||||
|
sb.append("public class ").append(tagClassName);
|
||||||
|
if (StringUtil.isNotEmpty(impl)) {
|
||||||
|
sb.append(" implements ").append(impl);
|
||||||
|
}
|
||||||
|
sb.append(" {\n");
|
||||||
|
consumer.accept(this);
|
||||||
|
sb.append("}\n");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuilderHelper addConstructor(TableInfo tableInfo) {
|
||||||
|
// 无参构造
|
||||||
|
sb.append(String.format("\tpublic %s() {\n\t}\n", tableInfo.getTagClassName()));
|
||||||
|
newLine();
|
||||||
|
//有参构造
|
||||||
|
sb.append("\tpublic ").append(tableInfo.getTagClassName()).append("(String alias) {\n" +
|
||||||
|
"\t\tthis._alias_q2Gv$ = alias;\n" +
|
||||||
|
"\t}\n");
|
||||||
|
newLine();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私有构造
|
||||||
|
*/
|
||||||
|
public StringBuilderHelper addPrivateConstructor(String tagClassName) {
|
||||||
|
sb.append(String.format("\tprivate %s() {\n\t}\n", tagClassName));
|
||||||
|
newLine();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuilderHelper addFields(TableInfo tableInfo) {
|
||||||
|
tableInfo.getFields().forEach(fieldInfo -> {
|
||||||
|
addComment("\t", fieldInfo.getComment());
|
||||||
|
sb.append(String.format("\tpublic final Column %s = new Column(this, %s.class, \"%s\", () -> this._alias_q2Gv$);\n",
|
||||||
|
fieldInfo.getProperty(), tableInfo.getSimpleClassName(), fieldInfo.getProperty()));
|
||||||
|
newLine();
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuilderHelper addTablesFields(List<TableInfo> tableInfos) {
|
||||||
|
tableInfos.forEach(tableInfo -> {
|
||||||
|
addComment("\t", tableInfo.getClassComment());
|
||||||
|
sb.append(String.format("\tpublic static final %s %s = new %s();\n",
|
||||||
|
tableInfo.getTagClassName(),
|
||||||
|
String.format(tableInfo.getTableAnnotation().tablesName(), tableInfo.getSimpleClassName()),
|
||||||
|
tableInfo.getTagClassName()));
|
||||||
|
newLine();
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuilderHelper addDefaultField(String simpleClassName) {
|
||||||
|
newLine();
|
||||||
|
sb.append("\tprivate static final Class<").append(simpleClassName).append("> _class_e76G$ = ").append(simpleClassName).append(".class;\n");
|
||||||
|
newLine();
|
||||||
|
sb.append("\tprivate String _alias_q2Gv$;\n");
|
||||||
|
newLine();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuilderHelper addMethod(TableInfo tableInfo) {
|
||||||
|
sb.append("\t@Override\n" +
|
||||||
|
"\tpublic Class<").append(tableInfo.getSimpleClassName()).append("> getColumnClass() {\n")
|
||||||
|
.append("\t\treturn this._class_e76G$;\n")
|
||||||
|
.append("\t}\n");
|
||||||
|
newLine();
|
||||||
|
sb.append("\t@Override\n" +
|
||||||
|
"\tpublic String getAlias() {\n" +
|
||||||
|
"\t\treturn this._alias_q2Gv$;\n" +
|
||||||
|
"\t}\n");
|
||||||
|
newLine();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilderHelper addComment(String prefix, String comment) {
|
||||||
|
if (StringUtil.isNotEmpty(comment)) {
|
||||||
|
sb.append(prefix).append("/**\n");
|
||||||
|
sb.append(Arrays.stream(comment.split("\n")).map(f -> prefix + " *" + f).collect(Collectors.joining("\n")));
|
||||||
|
sb.append("\n").append(prefix).append(" */");
|
||||||
|
newLine();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuilderHelper newLine() {
|
||||||
|
sb.append("\n");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package com.github.yulichang.processor.matedata;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.5.0
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class FieldInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性名。
|
||||||
|
*/
|
||||||
|
private String property;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注释。
|
||||||
|
*/
|
||||||
|
private String comment;
|
||||||
|
|
||||||
|
public FieldInfo(String property, String comment) {
|
||||||
|
this.property = property;
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProperty() {
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProperty(String property) {
|
||||||
|
this.property = property;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComment(String comment) {
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
FieldInfo fieldInfo = (FieldInfo) o;
|
||||||
|
return Objects.equals(property, fieldInfo.property);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
package com.github.yulichang.processor.matedata;
|
||||||
|
|
||||||
|
import com.github.yulichang.annotation.Table;
|
||||||
|
import com.github.yulichang.processor.utils.StringUtil;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.5.0
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class TableInfo {
|
||||||
|
|
||||||
|
public TableInfo(Table tableAnnotation) {
|
||||||
|
this.tableAnnotation = tableAnnotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String className;
|
||||||
|
|
||||||
|
private String simpleClassName;
|
||||||
|
|
||||||
|
private String classComment;
|
||||||
|
|
||||||
|
private String classPackage;
|
||||||
|
|
||||||
|
private Table tableAnnotation;
|
||||||
|
|
||||||
|
private Set<FieldInfo> fields;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成的类名
|
||||||
|
*/
|
||||||
|
public String getTagClassName() {
|
||||||
|
String tag = simpleClassName;
|
||||||
|
if (StringUtil.isNotEmpty(tableAnnotation.prefix()) || StringUtil.isNotEmpty(tableAnnotation.suffix())) {
|
||||||
|
tag = tableAnnotation.prefix() + tag + tableAnnotation.suffix();
|
||||||
|
} else {
|
||||||
|
tag = String.format(tableAnnotation.format(), tag);
|
||||||
|
}
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成类的路径
|
||||||
|
*/
|
||||||
|
public String getTagPackage() {
|
||||||
|
return classPackage + "." + tableAnnotation.packageName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClassName() {
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClassName(String className) {
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSimpleClassName() {
|
||||||
|
return simpleClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSimpleClassName(String simpleClassName) {
|
||||||
|
this.simpleClassName = simpleClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClassComment() {
|
||||||
|
return classComment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClassComment(String classComment) {
|
||||||
|
this.classComment = classComment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClassPackage() {
|
||||||
|
return classPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClassPackage(String classPackage) {
|
||||||
|
this.classPackage = classPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Table getTableAnnotation() {
|
||||||
|
return tableAnnotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTableAnnotation(Table tableAnnotation) {
|
||||||
|
this.tableAnnotation = tableAnnotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<FieldInfo> getFields() {
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFields(Set<FieldInfo> fields) {
|
||||||
|
this.fields = fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TableInfo{" +
|
||||||
|
"className='" + className + '\'' +
|
||||||
|
", simpleClassName='" + simpleClassName + '\'' +
|
||||||
|
", classComment='" + classComment + '\'' +
|
||||||
|
", classPackage='" + classPackage + '\'' +
|
||||||
|
", fields=" + fields +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.github.yulichang.processor.utils;
|
||||||
|
|
||||||
|
public final class StringUtil {
|
||||||
|
|
||||||
|
public static boolean isEmpty(String str) {
|
||||||
|
return str == null || str.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isNotEmpty(String str) {
|
||||||
|
return !isEmpty(str);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
com.github.yulichang.processor.EntityProcessor
|
@ -41,4 +41,30 @@
|
|||||||
<artifactId>jackson-core</artifactId>
|
<artifactId>jackson-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>com.github.yulichang</groupId>
|
||||||
|
<artifactId>mybatis-plus-join-processor</artifactId>
|
||||||
|
<version>1.4.13</version>
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.30</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
@ -2,11 +2,13 @@ package com.github.yulichang.test.join.entity;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.github.yulichang.annotation.Table;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Table
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString
|
@ToString
|
||||||
|
@ -3,6 +3,7 @@ package com.github.yulichang.test.join.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.github.yulichang.annotation.Table;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
@ -10,6 +11,7 @@ import lombok.experimental.Accessors;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Table
|
||||||
@Data
|
@Data
|
||||||
@ToString
|
@ToString
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
|
@ -4,12 +4,14 @@ import com.baomidou.mybatisplus.annotation.OrderBy;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.github.yulichang.annotation.Table;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Table
|
||||||
@Data
|
@Data
|
||||||
@ToString
|
@ToString
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
|
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||||
import com.github.yulichang.annotation.DynamicTableName;
|
import com.github.yulichang.annotation.DynamicTableName;
|
||||||
|
import com.github.yulichang.annotation.Table;
|
||||||
import com.github.yulichang.test.join.enums.Sex;
|
import com.github.yulichang.test.join.enums.Sex;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
@ -17,6 +18,7 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Table
|
||||||
@Data
|
@Data
|
||||||
@ToString
|
@ToString
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
|
@ -3,10 +3,12 @@ package com.github.yulichang.test.join.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.github.yulichang.annotation.Table;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Table
|
||||||
@Data
|
@Data
|
||||||
@TableName("user_dto")
|
@TableName("user_dto")
|
||||||
public class UserDto implements Serializable {
|
public class UserDto implements Serializable {
|
||||||
|
@ -4,10 +4,12 @@ package com.github.yulichang.test.join.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.github.yulichang.annotation.Table;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import lombok.experimental.FieldNameConstants;
|
import lombok.experimental.FieldNameConstants;
|
||||||
|
|
||||||
|
@Table
|
||||||
@Data
|
@Data
|
||||||
@ToString
|
@ToString
|
||||||
@FieldNameConstants
|
@FieldNameConstants
|
||||||
|
@ -4,14 +4,16 @@ package com.github.yulichang.test.join.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.github.yulichang.annotation.Table;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import lombok.experimental.FieldNameConstants;
|
import lombok.experimental.FieldNameConstants;
|
||||||
|
|
||||||
|
@Table
|
||||||
@Data
|
@Data
|
||||||
@ToString
|
@ToString
|
||||||
@FieldNameConstants
|
@FieldNameConstants
|
||||||
@TableName(value = "user_tenanta",autoResultMap = true)
|
@TableName(value = "user_tenanta", autoResultMap = true)
|
||||||
public class UserTenantaDO {
|
public class UserTenantaDO {
|
||||||
|
|
||||||
@TableId("id")
|
@TableId("id")
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,6 @@ import org.springframework.boot.test.context.SpringBootTest;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
public class UnionTest {
|
public class UnionTest {
|
||||||
|
|
||||||
@ -23,45 +22,6 @@ public class UnionTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void union() {
|
|
||||||
ThreadLocalUtils.set("SELECT t.id,t.pid,t.`name`,t.`json`,t.sex,t.head_img,t.create_time,t.address_id,t.address_id2,t.del,t.create_by,t.update_by FROM `user` t WHERE t.del=false AND (t.id = ?) UNION SELECT t.id,t.pid,t.`name`,t.`json`,t.sex,t.head_img,t.create_time,t.address_id,t.address_id2,t.del,t.create_by,t.update_by FROM `user` t WHERE (t.`name` = ? AND (t.`name` = ?)) UNION SELECT t.id,t.pid,t.`name`,t.`json`,t.sex,t.head_img,t.create_time,t.address_id,t.address_id2,t.del,t.create_by,t.update_by FROM `user` t WHERE t.del=false AND (t.pid = ?)");
|
|
||||||
MPJLambdaWrapper<UserDO> wrapper = JoinWrappers.lambda(UserDO.class)
|
|
||||||
.selectAll(UserDO.class)
|
|
||||||
.eq(UserDO::getId, 1);
|
|
||||||
MPJLambdaWrapper<UserDO> wrapper1 = JoinWrappers.lambda(UserDO.class)
|
|
||||||
.selectAll(UserDO.class)
|
|
||||||
.disableLogicDel()
|
|
||||||
.eq(UserDO::getName, "张三 2")
|
|
||||||
.and(w -> w.eq(UserDO::getName, "张三 2"));
|
|
||||||
MPJLambdaWrapper<UserDO> wrapper2 = JoinWrappers.lambda(UserDO.class)
|
|
||||||
.selectAll(UserDO.class)
|
|
||||||
.eq(UserDO::getPid, 2);
|
|
||||||
wrapper.union(wrapper1, wrapper2);
|
|
||||||
List<UserDO> list = wrapper.list();
|
|
||||||
|
|
||||||
System.out.println(wrapper.getUnionSql());
|
|
||||||
assert list.size() == 7 && list.get(0).getId() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void unionAll() {
|
|
||||||
ThreadLocalUtils.set("SELECT t.id FROM `user` t WHERE t.del = false AND (t.id = ?) UNION ALL SELECT t.id FROM address t UNION ALL SELECT t.id FROM area t WHERE t.del = false AND (t.id = ?)");
|
|
||||||
MPJLambdaWrapper<UserDO> wrapper = JoinWrappers.lambda(UserDO.class)
|
|
||||||
.select(UserDO::getId)
|
|
||||||
.eq(UserDO::getId, 1);
|
|
||||||
MPJLambdaWrapper<AddressDO> wrapper1 = JoinWrappers.lambda(AddressDO.class)
|
|
||||||
.select(AddressDO::getId)
|
|
||||||
.disableLogicDel();
|
|
||||||
MPJLambdaWrapper<AreaDO> wrapper2 = JoinWrappers.lambda(AreaDO.class)
|
|
||||||
.select(AreaDO::getId)
|
|
||||||
.eq(AreaDO::getId, 2);
|
|
||||||
wrapper.unionAll(wrapper1, wrapper2);
|
|
||||||
List<UserDO> list = wrapper.list();
|
|
||||||
|
|
||||||
assert list.size() == 23 && list.get(0).getId() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void unionAll1() {
|
void unionAll1() {
|
||||||
ThreadLocalUtils.set("SELECT t.id FROM `user` t WHERE t.del = false AND (t.id = ?) UNION ALL SELECT t.id FROM address t WHERE (t.id = ?) UNION ALL SELECT (SELECT st.id FROM area st WHERE st.del = false AND (st.id = ? AND (st.id = ?))) AS id FROM area t WHERE t.del = false AND (t.id = ? AND (t.id = ?))");
|
ThreadLocalUtils.set("SELECT t.id FROM `user` t WHERE t.del = false AND (t.id = ?) UNION ALL SELECT t.id FROM address t WHERE (t.id = ?) UNION ALL SELECT (SELECT st.id FROM area st WHERE st.del = false AND (st.id = ? AND (st.id = ?))) AS id FROM area t WHERE t.del = false AND (t.id = ? AND (t.id = ?))");
|
||||||
|
1
pom.xml
1
pom.xml
@ -36,6 +36,7 @@
|
|||||||
<module>mybatis-plus-join-annotation</module>
|
<module>mybatis-plus-join-annotation</module>
|
||||||
<module>mybatis-plus-join-extension</module>
|
<module>mybatis-plus-join-extension</module>
|
||||||
<module>mybatis-plus-join-solon-plugin</module>
|
<module>mybatis-plus-join-solon-plugin</module>
|
||||||
|
<module>mybatis-plus-join-processor</module>
|
||||||
<module>mybatis-plus-join-test</module>
|
<module>mybatis-plus-join-test</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user