fix: 修复apt问题

This commit is contained in:
yulichang 2024-07-16 03:43:20 +08:00
parent f8e51aa958
commit 658bb2bb59
9 changed files with 128 additions and 101 deletions

View File

@ -1,6 +1,8 @@
package com.github.yulichang.apt; package com.github.yulichang.apt;
public interface BaseColumn<T> { import java.io.Serializable;
public interface BaseColumn<T> extends Serializable {
Class<T> getColumnClass(); Class<T> getColumnClass();

View File

@ -3,11 +3,12 @@ package com.github.yulichang.apt;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import java.io.Serializable;
import java.util.function.Supplier; import java.util.function.Supplier;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
public class Column { public class Column implements Serializable {
private BaseColumn<?> root; private BaseColumn<?> root;

View File

@ -1,51 +1,70 @@
package com.github.yulichang.toolkit; package com.github.yulichang.toolkit;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.github.yulichang.apt.BaseColumn;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList; import java.io.Serializable;
import java.util.HashMap; import java.util.Collection;
import java.util.List; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
public class TableMap<K, V> { public class TableMap implements Serializable {
@Setter
@Getter
private TableMap parent;
@Getter @Getter
private final K root; private final BaseColumn<?> root;
@Getter @Getter
private final String rootAlias; @Setter
private String rootAlias;
private final Map<K, V> map = new HashMap<>(); private final Map<BaseColumn<?>, String> tableMap = new LinkedHashMap<>();
private final List<K> list = new ArrayList<>(); public TableMap(BaseColumn<?> root, String rootAlias) {
public TableMap(K root, String rootAlias) {
this.root = root; this.root = root;
this.rootAlias = rootAlias; this.rootAlias = rootAlias;
} }
public V put(K key, V value) { public String put(BaseColumn<?> key, String value) {
V v = this.map.put(key, value); return tableMap.put(key, value);
if (null == v) { }
this.list.add(key);
public String get(BaseColumn<?> key) {
return get(this, key);
}
private String get(TableMap tableMap, BaseColumn<?> key) {
if (null != key.getAlias()) {
return key.getAlias();
} }
return v; if (key == tableMap.root) {
return tableMap.rootAlias;
}
String pf = tableMap.tableMap.get(key);
if (null == pf) {
if (tableMap.parent == null) {
throw ExceptionUtils.mpe("table not found %s", key.getColumnClass().getName());
} else {
return get(tableMap.parent, key);
}
}
return pf;
} }
public V get(K key) { public Collection<BaseColumn<?>> keyList() {
return this.map.get(key); return tableMap.keySet();
}
public List<K> keyList() {
return this.list;
} }
public boolean isEmpty() { public boolean isEmpty() {
return this.map.isEmpty(); return this.tableMap.isEmpty();
} }
public void clear() { public void clear() {
this.map.clear(); this.tableMap.clear();
this.list.clear();
} }
} }

View File

@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.annotation.OrderBy;
import com.baomidou.mybatisplus.core.conditions.SharedString; import com.baomidou.mybatisplus.core.conditions.SharedString;
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments; import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
import com.baomidou.mybatisplus.core.metadata.TableInfo; 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.Constants;
import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.StringUtils;
@ -109,7 +108,7 @@ public abstract class AptAbstractWrapper<T, Children extends AptAbstractWrapper<
* apt别名对应 * apt别名对应
*/ */
@Getter @Getter
protected TableMap<BaseColumn<?>, String> aptIndex; protected TableMap aptIndex;
/** /**
* 构造方法 * 构造方法
@ -185,19 +184,6 @@ public abstract class AptAbstractWrapper<T, Children extends AptAbstractWrapper<
return 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 @Override
protected String columnsToString(Column... columns) { protected String columnsToString(Column... columns) {
return Arrays.stream(columns).map(this::columnToString) return Arrays.stream(columns).map(this::columnToString)
@ -210,7 +196,7 @@ public abstract class AptAbstractWrapper<T, Children extends AptAbstractWrapper<
if (Objects.nonNull(pf)) { if (Objects.nonNull(pf)) {
return pf + StringPool.DOT + getCache(column).getColumn(); return pf + StringPool.DOT + getCache(column).getColumn();
} }
return getPrefix(column.getRoot()) + StringPool.DOT + getCache(column).getColumn(); return this.aptIndex.get(column.getRoot()) + StringPool.DOT + getCache(column).getColumn();
} }
protected SelectCache getCache(Column fn) { protected SelectCache getCache(Column fn) {
@ -257,7 +243,7 @@ public abstract class AptAbstractWrapper<T, Children extends AptAbstractWrapper<
if (aptIndex.isEmpty()) { if (aptIndex.isEmpty()) {
return StringPool.EMPTY; return StringPool.EMPTY;
} }
return aptIndex.keyList().stream().map(key -> LogicInfoUtils.getLogicInfoApt(key.getColumnClass(), getPrefix(key))) return aptIndex.keyList().stream().map(key -> LogicInfoUtils.getLogicInfoApt(key.getColumnClass(), this.aptIndex.get(key)))
.collect(Collectors.joining(StringPool.SPACE)); .collect(Collectors.joining(StringPool.SPACE));
} }
return StringPool.EMPTY; return StringPool.EMPTY;
@ -408,7 +394,7 @@ public abstract class AptAbstractWrapper<T, Children extends AptAbstractWrapper<
lastSql = SharedString.emptyString(); lastSql = SharedString.emptyString();
sqlComment = SharedString.emptyString(); sqlComment = SharedString.emptyString();
sqlFirst = SharedString.emptyString(); sqlFirst = SharedString.emptyString();
aptIndex = new TableMap<>(this.baseColumn, this.alias); aptIndex = new TableMap(this.baseColumn, this.alias);
} }
@Override @Override

View File

@ -94,7 +94,7 @@ public class AptQueryWrapper<T> extends AptAbstractWrapper<T, AptQueryWrapper<T>
protected AptQueryWrapper(T entity, BaseColumn<T> baseColumn, SharedString sqlSelect, AtomicInteger paramNameSeq, protected AptQueryWrapper(T entity, BaseColumn<T> baseColumn, SharedString sqlSelect, AtomicInteger paramNameSeq,
Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments, SharedString paramAlias, Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments, SharedString paramAlias,
SharedString lastSql, SharedString sqlComment, SharedString sqlFirst, SharedString lastSql, SharedString sqlComment, SharedString sqlFirst,
TableMap<BaseColumn<?>, String> aptIndex, Integer index, String keyWord, Class<?> joinClass, String tableName, TableMap aptIndex, Integer index, String keyWord, Class<?> joinClass, String tableName,
BiPredicate<Object, IfExistsSqlKeyWordEnum> IfExists) { BiPredicate<Object, IfExistsSqlKeyWordEnum> IfExists) {
super(baseColumn); super(baseColumn);
super.setEntity(entity); super.setEntity(entity);
@ -108,7 +108,9 @@ public class AptQueryWrapper<T> extends AptAbstractWrapper<T, AptQueryWrapper<T>
this.lastSql = lastSql; this.lastSql = lastSql;
this.sqlComment = sqlComment; this.sqlComment = sqlComment;
this.sqlFirst = sqlFirst; this.sqlFirst = sqlFirst;
this.aptIndex = aptIndex; if (aptIndex != null) {
this.aptIndex = aptIndex;
}
this.index = index; this.index = index;
this.keyWord = keyWord; this.keyWord = keyWord;
this.joinClass = joinClass; this.joinClass = joinClass;
@ -188,20 +190,17 @@ public class AptQueryWrapper<T> extends AptAbstractWrapper<T, AptQueryWrapper<T>
* 子查询 * 子查询
*/ */
public <E, F> AptQueryWrapper<T> selectSub(BaseColumn<E> baseColumn, Consumer<AptQueryWrapper<E>> consumer, SFunction<F, ?> alias) { 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(), AptQueryWrapper<E> wrapper = new AptQueryWrapper<E>(null, baseColumn, SharedString.emptyString(),
paramNameSeq, paramNameValuePairs, new MergeSegments(), new SharedString(this.paramAlias paramNameSeq, paramNameValuePairs, new MergeSegments(), new SharedString(this.paramAlias
.getStringValue()), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(), .getStringValue()), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(),
this.aptIndex, null, null, null, null, ifExists) { null, null, null, null, null, ifExists) {
}; };
wrapper.alias = st; wrapper.aptIndex.setParent(this.aptIndex);
wrapper.subTableAlias = st; if (null == baseColumn.getAlias()) {
wrapper.alias = ConfigProperties.subQueryAlias;
wrapper.aptIndex.setRootAlias(ConfigProperties.subQueryAlias);
}
wrapper.subTableAlias = ConfigProperties.subQueryAlias;
consumer.accept(wrapper); consumer.accept(wrapper);
addCustomWrapper(wrapper); addCustomWrapper(wrapper);
String name = LambdaUtils.getName(alias); String name = LambdaUtils.getName(alias);
@ -279,11 +278,11 @@ public class AptQueryWrapper<T> extends AptAbstractWrapper<T, AptQueryWrapper<T>
} }
if (i.isFunc()) { if (i.isFunc()) {
return String.format(i.getFunc().getSql(), Arrays.stream(i.getColumns()).map(c -> return String.format(i.getFunc().getSql(), Arrays.stream(i.getColumns()).map(c ->
getPrefix(c.getRoot()) + StringPool.DOT + i.getColumn()).toArray()) + Constant.AS + i.getAlias(); this.aptIndex.get(c.getRoot()) + StringPool.DOT + i.getColumn()).toArray()) + Constant.AS + i.getAlias();
} else { } else {
String prefix; String prefix;
if (null == i.getTableAlias() && null != i.getBaseColumn()) { if (null == i.getTableAlias() && null != i.getBaseColumn()) {
prefix = getPrefix(i.getBaseColumn()); prefix = this.aptIndex.get(i.getBaseColumn());
} else { } else {
prefix = i.getTableAlias(); prefix = i.getTableAlias();
} }

View File

@ -528,13 +528,11 @@ public abstract class JoinAbstractWrapper<T, Children extends JoinAbstractWrappe
} }
protected <X, S> Children addCondition(boolean condition, Column column, SqlKeyword sqlKeyword, Column val) { protected <X, S> Children addCondition(boolean condition, Column column, SqlKeyword sqlKeyword, Column val) {
return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), sqlKeyword, columnToSqlSegment(val) return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), sqlKeyword, columnToSqlSegment(val)));
));
} }
protected Children addCondition(boolean condition, String column, SqlKeyword sqlKeyword, Object val) { protected Children addCondition(boolean condition, String column, SqlKeyword sqlKeyword, Object val) {
return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), sqlKeyword, return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), sqlKeyword, () -> formatParam(null, val)));
() -> formatParam(null, val)));
} }
/** /**

View File

@ -1,13 +1,14 @@
package com.github.yulichang.test.join.apt.unit; package com.github.yulichang.test.join.apt.unit;
import com.github.yulichang.test.join.entity.AddressDO;
import com.github.yulichang.test.join.entity.AreaDO;
import com.github.yulichang.test.join.entity.UserDO; import com.github.yulichang.test.join.entity.UserDO;
import com.github.yulichang.test.join.entity.apt.AddressDOCol;
import com.github.yulichang.test.join.entity.apt.AreaDOCol;
import com.github.yulichang.test.join.entity.apt.UserDOCol;
import com.github.yulichang.test.util.EnabledIfConfig; import com.github.yulichang.test.util.EnabledIfConfig;
import com.github.yulichang.test.util.Reset; import com.github.yulichang.test.util.Reset;
import com.github.yulichang.test.util.ThreadLocalUtils; import com.github.yulichang.test.util.ThreadLocalUtils;
import com.github.yulichang.toolkit.JoinWrappers; import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.github.yulichang.wrapper.apt.AptQueryWrapper;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@ -29,39 +30,52 @@ public class SelectSubTest {
@Test @Test
void sub() { void sub() {
ThreadLocalUtils.set("SELECT (SELECT st.id FROM `user` st WHERE st.del = false AND (st.id = t.id AND st.id = ?) LIMIT 1) AS id, (SELECT st.id FROM `user` st WHERE st.del = false AND (st.id = t.id AND st.id = ?) LIMIT 1) AS name FROM `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) WHERE t.del = false AND t1.del = false AND (t.id <= ?)"); ThreadLocalUtils.set("SELECT (SELECT st.id FROM `user` st WHERE st.del = false AND (st.id = t.id AND st.id = ?) LIMIT 1) AS id, (SELECT st.id FROM `user` st WHERE st.del = false AND (st.id = t.id AND st.id = ?) LIMIT 1) AS name FROM `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) WHERE t.del = false AND t1.del = false AND (t.id <= ?)");
MPJLambdaWrapper<UserDO> wrapper = JoinWrappers.lambda(UserDO.class) UserDOCol u = new UserDOCol();
.selectSub(UserDO.class, w -> w.select(UserDO::getId) UserDOCol sb = new UserDOCol();
.eq(UserDO::getId, UserDO::getId) UserDOCol sb2 = new UserDOCol();
.eq(UserDO::getId, 2) AddressDOCol addr = new AddressDOCol();
AptQueryWrapper<UserDO> wrapper = JoinWrappers.apt(u)
.selectSub(sb, w -> w.select(sb.id)
.eq(sb.id, u.id)
.eq(sb.id, 2)
.last("limit 1"), UserDO::getId) .last("limit 1"), UserDO::getId)
.selectSub(UserDO.class, w -> w.select(UserDO::getId) .selectSub(sb2, w -> w.select(sb2.id)
.eq(UserDO::getId, UserDO::getId) .eq(sb2.id, u.id)
.eq(UserDO::getId, 3) .eq(sb2.id, 3)
.last("limit 1"), UserDO::getName) .last("limit 1"), UserDO::getName)
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId) .leftJoin(addr, addr.userId, u.id)
.le(UserDO::getId, 100); .le(u.id, 100);
wrapper.list(); wrapper.list();
UserDOCol u1 = new UserDOCol();
AddressDOCol addr1 = new AddressDOCol();
AreaDOCol area = new AreaDOCol();
ThreadLocalUtils.set("SELECT (SELECT st.id FROM area st WHERE st.del = false AND (st.id = t1.id) LIMIT 1) AS id FROM `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) WHERE t.del = false AND t1.del = false AND (t.id <= ?)"); ThreadLocalUtils.set("SELECT (SELECT st.id FROM area st WHERE st.del = false AND (st.id = t1.id) LIMIT 1) AS id FROM `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) WHERE t.del = false AND t1.del = false AND (t.id <= ?)");
MPJLambdaWrapper<UserDO> wrapper1 = JoinWrappers.lambda(UserDO.class) AptQueryWrapper<UserDO> wrapper1 = JoinWrappers.apt(u1)
.selectSub(AreaDO.class, w -> w.select(AreaDO::getId) .selectSub(area, w -> w.select(area.id)
.eq(AreaDO::getId, AddressDO::getId) .eq(area.id, addr1.id)
.last("limit 1"), UserDO::getId) .last("limit 1"), UserDO::getId)
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId) .leftJoin(addr1, addr1.userId, u1.id)
.le(UserDO::getId, 100); .le(u1.id, 100);
wrapper1.list(); wrapper1.list();
} }
@Test @Test
void sub1() { void sub1() {
ThreadLocalUtils.set("SELECT (SELECT st.id FROM `area` st WHERE st.del = false AND (st.id = t1.id) LIMIT 1) AS id FROM `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) WHERE t.del = false AND t1.del = false AND (t.id <= ?)"); ThreadLocalUtils.set("SELECT (SELECT st.id FROM `area` st WHERE st.del = false AND (st.id = t1.id) LIMIT 1) AS id FROM `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) WHERE t.del = false AND t1.del = false AND (t.id <= ?)");
MPJLambdaWrapper<UserDO> wrapper1 = JoinWrappers.lambda(UserDO.class) UserDOCol u = new UserDOCol();
.selectSub(AreaDO.class, w -> w.select(AreaDO::getId) AddressDOCol addr = new AddressDOCol();
.eq(AreaDO::getId, AddressDO::getId) AreaDOCol ar = new AreaDOCol();
AptQueryWrapper<UserDO> wrapper1 = JoinWrappers.apt(u)
.selectSub(ar, w -> w.select(ar.id)
.eq(ar.id, addr.id)
.setTableName(t -> "`" + t + "`") .setTableName(t -> "`" + t + "`")
.last("limit 1"), UserDO::getId) .last("limit 1"), UserDO::getId)
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId) .leftJoin(addr, addr.userId, u.id)
.le(UserDO::getId, 100); .le(u.id, 100);
wrapper1.list(); wrapper1.list();
} }
} }

View File

@ -1,12 +1,14 @@
package com.github.yulichang.test.join.apt.unit; package com.github.yulichang.test.join.apt.unit;
import com.github.yulichang.test.join.entity.AddressDO;
import com.github.yulichang.test.join.entity.AreaDO; import com.github.yulichang.test.join.entity.AreaDO;
import com.github.yulichang.test.join.entity.UserDO; import com.github.yulichang.test.join.entity.UserDO;
import com.github.yulichang.test.join.entity.apt.AddressDOCol;
import com.github.yulichang.test.join.entity.apt.AreaDOCol;
import com.github.yulichang.test.join.entity.apt.UserDOCol;
import com.github.yulichang.test.util.Reset; import com.github.yulichang.test.util.Reset;
import com.github.yulichang.test.util.ThreadLocalUtils; import com.github.yulichang.test.util.ThreadLocalUtils;
import com.github.yulichang.toolkit.JoinWrappers; import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.github.yulichang.wrapper.apt.AptQueryWrapper;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@ -25,20 +27,26 @@ public class UnionTest {
@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 = ?))");
MPJLambdaWrapper<UserDO> wrapper = JoinWrappers.lambda(UserDO.class)
.select(UserDO::getId) UserDOCol u = new UserDOCol();
.eq(UserDO::getId, 1) AddressDOCol addr = new AddressDOCol();
.unionAll(AddressDO.class, union -> union AreaDOCol area = new AreaDOCol();
.select(AddressDO::getId) AreaDOCol areaSb = new AreaDOCol();
AptQueryWrapper<UserDO> wrapper = JoinWrappers.apt(u)
.select(u.id)
.eq(u.id, 1)
.unionAll(addr, union -> union
.select(addr.id)
.disableLogicDel() .disableLogicDel()
.eq(UserDO::getId, 2)) .eq(addr.id, 2))
.unionAll(AreaDO.class, union -> union .unionAll(area, union -> union
.selectSub(AreaDO.class, sub -> sub .selectSub(areaSb, sub -> sub
.select(AreaDO::getId) .select(areaSb.id)
.eq(AreaDO::getId, 3) .eq(areaSb.id, 3)
.and(and -> and.eq(AreaDO::getId, 4)), AreaDO::getId) .and(and -> and.eq(areaSb.id, 4)), AreaDO::getId)
.eq(AreaDO::getId, 5) .eq(area.id, 5)
.and(and -> and.eq(AreaDO::getId, 6))); .and(and -> and.eq(area.id, 6)));
List<UserDO> list = wrapper.list(); List<UserDO> list = wrapper.list();
assert list.size() == 2 && list.get(0).getId() != null; assert list.size() == 2 && list.get(0).getId() != null;
} }

View File

@ -31,7 +31,7 @@ public class UnionTest {
.unionAll(AddressDO.class, union -> union .unionAll(AddressDO.class, union -> union
.select(AddressDO::getId) .select(AddressDO::getId)
.disableLogicDel() .disableLogicDel()
.eq(UserDO::getId, 2)) .eq(AddressDO::getId, 2))
.unionAll(AreaDO.class, union -> union .unionAll(AreaDO.class, union -> union
.selectSub(AreaDO.class, sub -> sub .selectSub(AreaDO.class, sub -> sub
.select(AreaDO::getId) .select(AreaDO::getId)