mirror of
https://gitee.com/best_handsome/mybatis-plus-join
synced 2025-07-11 00:02:22 +08:00
fix https://gitee.com/best_handsome/mybatis-plus-join/issues/I8WPCL https://gitee.com/best_handsome/mybatis-plus-join/issues/I8WP8Q https://gitee.com/best_handsome/mybatis-plus-join/issues/I83IEV https://github.com/yulichang/mybatis-plus-join/issues/89
This commit is contained in:
parent
48c1b6e8a1
commit
0475d410d0
@ -10,7 +10,7 @@ import java.lang.annotation.*;
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Documented
|
||||
@SuppressWarnings({"unused"})
|
||||
@SuppressWarnings("unused")
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
|
||||
public @interface EntityMapping {
|
||||
|
@ -2,15 +2,13 @@ package com.github.yulichang.interceptor;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisPlusVersion;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
|
||||
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||
import com.github.yulichang.adapter.base.tookit.VersionUtils;
|
||||
import com.github.yulichang.config.ConfigProperties;
|
||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||
import com.github.yulichang.query.MPJQueryWrapper;
|
||||
import com.github.yulichang.toolkit.Constant;
|
||||
import com.github.yulichang.toolkit.MPJReflectionKit;
|
||||
import com.github.yulichang.toolkit.MPJTableMapperHelper;
|
||||
import com.github.yulichang.toolkit.TableHelper;
|
||||
import com.github.yulichang.toolkit.*;
|
||||
import com.github.yulichang.toolkit.support.FieldCache;
|
||||
import com.github.yulichang.wrapper.interfaces.SelectWrapper;
|
||||
import com.github.yulichang.wrapper.resultmap.IResult;
|
||||
@ -50,7 +48,7 @@ public class MPJInterceptor implements Interceptor {
|
||||
private static final List<ResultMapping> EMPTY_RESULT_MAPPING = new ArrayList<>(0);
|
||||
|
||||
/**
|
||||
* 缓存MappedStatement,不需要每次都去重新构建MappedStatement
|
||||
* 缓存MappedStatement,不需要每次都去构建MappedStatement
|
||||
*/
|
||||
private static final Map<String, Map<Configuration, MappedStatement>> MS_CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
@ -199,11 +197,23 @@ public class MPJInterceptor implements Interceptor {
|
||||
}
|
||||
} else {
|
||||
FieldCache field = fieldMap.get(i.getColumProperty());
|
||||
columnSet.add(i.getTagColumn());
|
||||
if (Objects.nonNull(field)) {
|
||||
ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), i.getColumProperty(),
|
||||
i.getTagColumn(), field.getType());
|
||||
resultMappings.add(selectToResult(wrapper.getEntityClass(), i, field.getType(), builder));
|
||||
if (StringUtils.isNotBlank(i.getTagColumn())) {
|
||||
columnSet.add(i.getTagColumn());
|
||||
if (Objects.nonNull(field)) {
|
||||
ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), i.getColumProperty(),
|
||||
i.getTagColumn(), field.getType());
|
||||
resultMappings.add(selectToResult(wrapper.getEntityClass(), i, field.getType(), builder));
|
||||
}
|
||||
} else if (wrapper.isResultMap()) {
|
||||
ThrowOptional.tryDo(() -> JSqlParserHelper.paresColum(wrapper, i.getColumn(), col -> {
|
||||
FieldCache strField = fieldMap.get(col);
|
||||
columnSet.add(col);
|
||||
if (Objects.nonNull(strField)) {
|
||||
ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), col,
|
||||
col, strField.getType());
|
||||
resultMappings.add(selectToResult(wrapper.getEntityClass(), i, strField.getType(), builder));
|
||||
}
|
||||
})).catchDo();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -430,7 +440,7 @@ public class MPJInterceptor implements Interceptor {
|
||||
public void setProperties(Properties properties) {
|
||||
try {
|
||||
Interceptor.super.setProperties(properties);
|
||||
} catch (Exception ignored) {
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,7 @@ public class KtLambdaWrapper<T> extends KtAbstractLambdaWrapper<T, KtLambdaWrapp
|
||||
consumer.accept(wrapper);
|
||||
addCustomWrapper(wrapper);
|
||||
this.selectColumns.add(new SelectSub(() -> KtWrapperUtils.buildSubSqlByWrapper(
|
||||
clazz, wrapper, alias.getName()), hasAlias, this.alias));
|
||||
clazz, wrapper, alias.getName()), hasAlias, this.alias, alias.getName()));
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,8 @@ public interface Query<Children> extends Serializable {
|
||||
* @param columns 列
|
||||
*/
|
||||
default Children select(String... columns) {
|
||||
getSelectColum().addAll(Arrays.stream(columns).map(i -> new SelectString(i, isHasAlias(), getAlias())).collect(Collectors.toList()));
|
||||
getSelectColum().addAll(Arrays.stream(columns).map(i ->
|
||||
new SelectString(i, null)).collect(Collectors.toList()));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
@ -100,7 +101,7 @@ public interface Query<Children> extends Serializable {
|
||||
* @param column 列
|
||||
*/
|
||||
default Children selectAs(String column, KProperty<?> alias) {
|
||||
getSelectColum().add(new SelectString(column + Constants.AS + alias.getName(), isHasAlias(), getAlias()));
|
||||
getSelectColum().add(new SelectString(column + Constants.AS + alias.getName(), alias.getName()));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
@ -113,8 +114,7 @@ public interface Query<Children> extends Serializable {
|
||||
Map<String, SelectCache> cacheMap = ColumnCache.getMapField(KtUtils.ref(column));
|
||||
SelectCache cache = cacheMap.get(column.getName());
|
||||
getSelectColum().add(new SelectString(
|
||||
index + Constants.DOT + cache.getColumn() + Constants.AS + alias.getName(),
|
||||
isHasAlias(), getAlias()));
|
||||
index + Constants.DOT + cache.getColumn() + Constants.AS + alias.getName(), alias.getName()));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,55 @@
|
||||
package com.github.yulichang.toolkit;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.github.yulichang.wrapper.interfaces.SelectWrapper;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import net.sf.jsqlparser.statement.Statement;
|
||||
import net.sf.jsqlparser.statement.select.*;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
* @since 1.4.10
|
||||
*/
|
||||
public final class JSqlParserHelper {
|
||||
|
||||
/**
|
||||
* 解析sql select字段 刚接触JSqlParser有更好的用法欢迎PR
|
||||
*
|
||||
* @param selectSql 要解析的select sql片段
|
||||
* @param columConsumer 解析的字段处理
|
||||
*/
|
||||
public static void paresColum(SelectWrapper<?, ?> wrapper, String selectSql, Consumer<String> columConsumer) throws Exception {
|
||||
Statement statement = CCJSqlParserUtil.parse(String.format("SELECT %s FROM table %s %s", selectSql, wrapper.getAlias(), wrapper.getFrom()));
|
||||
if (statement instanceof Select) {
|
||||
Select select = (Select) statement;
|
||||
SelectBody selectBody = select.getSelectBody();
|
||||
if (selectBody instanceof PlainSelect) {
|
||||
PlainSelect plainSelect = (PlainSelect) selectBody;
|
||||
if (CollectionUtils.isNotEmpty(plainSelect.getSelectItems())) {
|
||||
for (SelectItem item : plainSelect.getSelectItems()) {
|
||||
if (item instanceof SelectExpressionItem) {
|
||||
String col;
|
||||
SelectExpressionItem selectExpressionItem = (SelectExpressionItem) item;
|
||||
if (null == selectExpressionItem.getAlias()) {
|
||||
if (selectExpressionItem.getExpression() instanceof Column) {
|
||||
col = StringUtils.getTargetColumn(((Column) selectExpressionItem.getExpression()).getColumnName());
|
||||
} else {
|
||||
col = StringUtils.getTargetColumn(selectExpressionItem.getExpression().toString());
|
||||
}
|
||||
} else {
|
||||
col = StringUtils.getTargetColumn(selectExpressionItem.getAlias().getName());
|
||||
}
|
||||
if (StringUtils.isNotBlank(col)) {
|
||||
columConsumer.accept(col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -33,7 +33,11 @@ public class ThrowOptional {
|
||||
try {
|
||||
this.doSomething.doSomething();
|
||||
} catch (Throwable ignored) {
|
||||
doSomething.doSomething();
|
||||
try {
|
||||
doSomething.doSomething();
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,6 +52,6 @@ public class ThrowOptional {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface DoSomething {
|
||||
void doSomething();
|
||||
void doSomething() throws Throwable;
|
||||
}
|
||||
}
|
||||
|
@ -220,7 +220,8 @@ public class MPJLambdaWrapper<T> extends JoinAbstractLambdaWrapper<T, MPJLambdaW
|
||||
wrapper.subTableAlias = st;
|
||||
consumer.accept(wrapper);
|
||||
addCustomWrapper(wrapper);
|
||||
this.selectColumns.add(new SelectSub(() -> WrapperUtils.buildSubSqlByWrapper(clazz, wrapper, LambdaUtils.getName(alias)), hasAlias, this.alias));
|
||||
String name = LambdaUtils.getName(alias);
|
||||
this.selectColumns.add(new SelectSub(() -> WrapperUtils.buildSubSqlByWrapper(clazz, wrapper, name), hasAlias, this.alias, name));
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package com.github.yulichang.wrapper.interfaces;
|
||||
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.support.SFunction;
|
||||
import com.github.yulichang.toolkit.Asserts;
|
||||
import com.github.yulichang.toolkit.LambdaUtils;
|
||||
@ -15,7 +16,6 @@ import com.github.yulichang.wrapper.enums.DefaultFuncEnum;
|
||||
import com.github.yulichang.wrapper.segments.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
@ -90,7 +90,7 @@ public interface Query<Children> extends Serializable {
|
||||
* @param columns 列
|
||||
*/
|
||||
default Children select(String... columns) {
|
||||
getSelectColum().addAll(Arrays.stream(columns).map(i -> new SelectString(i, isHasAlias(), getAlias())).collect(Collectors.toList()));
|
||||
getSelectColum().add(new SelectString(String.join(StringPool.COMMA, columns), null));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
@ -100,7 +100,7 @@ public interface Query<Children> extends Serializable {
|
||||
* @param column 列
|
||||
*/
|
||||
default <E> Children selectAs(String column, SFunction<E, ?> alias) {
|
||||
getSelectColum().add(new SelectString(column + Constants.AS + LambdaUtils.getName(alias), isHasAlias(), getAlias()));
|
||||
getSelectColum().add(new SelectString(column + Constants.AS + LambdaUtils.getName(alias), LambdaUtils.getName(alias)));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
@ -113,8 +113,7 @@ public interface Query<Children> extends Serializable {
|
||||
Map<String, SelectCache> cacheMap = ColumnCache.getMapField(LambdaUtils.getEntityClass(column));
|
||||
SelectCache cache = cacheMap.get(LambdaUtils.getName(column));
|
||||
getSelectColum().add(new SelectString(
|
||||
index + Constants.DOT + cache.getColumn() + Constants.AS + LambdaUtils.getName(alias),
|
||||
isHasAlias(), getAlias()));
|
||||
index + Constants.DOT + cache.getColumn() + Constants.AS + LambdaUtils.getName(alias), LambdaUtils.getName(alias)));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
|
@ -21,4 +21,8 @@ public interface SelectWrapper<Entity, Children> {
|
||||
boolean isResultMap();
|
||||
|
||||
List<?> getResultMapMybatisLabel();
|
||||
|
||||
String getFrom();
|
||||
|
||||
String getAlias();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.github.yulichang.wrapper.segments;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
||||
import org.apache.ibatis.type.TypeHandler;
|
||||
|
||||
@ -13,14 +14,11 @@ import org.apache.ibatis.type.TypeHandler;
|
||||
public class SelectString implements Select {
|
||||
private final String column;
|
||||
|
||||
private final boolean hasTableAlias;
|
||||
private final String tagProperty;
|
||||
|
||||
private final String tableAlias;
|
||||
|
||||
public SelectString(String column, boolean hasTableAlias, String tableAlias) {
|
||||
public SelectString(String column, String tagProperty) {
|
||||
this.column = column;
|
||||
this.hasTableAlias = hasTableAlias;
|
||||
this.tableAlias = tableAlias;
|
||||
this.tagProperty = null == tagProperty ? null : StringUtils.getTargetColumn(tagProperty);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -35,12 +33,12 @@ public class SelectString implements Select {
|
||||
|
||||
@Override
|
||||
public boolean isHasTableAlias() {
|
||||
return this.hasTableAlias;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return this.tableAlias;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -60,12 +58,12 @@ public class SelectString implements Select {
|
||||
|
||||
@Override
|
||||
public String getTagColumn() {
|
||||
return null;
|
||||
return tagProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumProperty() {
|
||||
return null;
|
||||
return tagProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,6 +2,7 @@ package com.github.yulichang.wrapper.segments;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
||||
import org.apache.ibatis.type.TypeHandler;
|
||||
|
||||
@ -22,10 +23,13 @@ public class SelectSub implements Select {
|
||||
|
||||
private final String tableAlias;
|
||||
|
||||
public SelectSub(Supplier<String> column, boolean hasTableAlias, String tableAlias) {
|
||||
private final String tagProperty;
|
||||
|
||||
public SelectSub(Supplier<String> column, boolean hasTableAlias, String tableAlias,String tagProperty) {
|
||||
this.column = column;
|
||||
this.hasTableAlias = hasTableAlias;
|
||||
this.tableAlias = tableAlias;
|
||||
this.tagProperty = null == tagProperty ? null : StringUtils.getTargetColumn(tagProperty);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -65,12 +69,12 @@ public class SelectSub implements Select {
|
||||
|
||||
@Override
|
||||
public String getTagColumn() {
|
||||
return null;
|
||||
return tagProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumProperty() {
|
||||
return null;
|
||||
return tagProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,15 +64,15 @@ class LambdaWrapperTest {
|
||||
@Test
|
||||
void testSelectSort() {
|
||||
ThreadLocalUtils.set("SELECT t.id, t.user_id, t.tenant_id FROM user_tenant t WHERE t.tenant_id = 1");
|
||||
MPJLambdaWrapper<UserTenantDO> lambda = JoinWrappers.lambda(UserTenantDO.class);
|
||||
lambda.selectAsClass(UserTenantDO.class, UserTenantDTO.class);
|
||||
MPJLambdaWrapper<UserTenantDO> lambda = JoinWrappers.lambda(UserTenantDO.class)
|
||||
.selectAsClass(UserTenantDO.class, UserTenantDTO.class);
|
||||
List<UserTenantDO> list = userTenantMapper.selectJoinList(UserTenantDO.class, lambda);
|
||||
assert list.size() == 5 && list.get(0).getIdea() != null;
|
||||
|
||||
|
||||
ThreadLocalUtils.set("SELECT t.tenant_id, t.user_id, t.id FROM user_tenant t WHERE t.tenant_id = 1");
|
||||
MPJLambdaWrapper<UserTenantDO> lambda1 = JoinWrappers.lambda(UserTenantDO.class);
|
||||
lambda1.selectAsClass(UserTenantDO.class, UserTenantDescDTO.class);
|
||||
MPJLambdaWrapper<UserTenantDO> lambda1 = JoinWrappers.lambda(UserTenantDO.class)
|
||||
.selectAsClass(UserTenantDO.class, UserTenantDescDTO.class);
|
||||
List<UserTenantDO> list1 = userTenantMapper.selectJoinList(UserTenantDO.class, lambda1);
|
||||
assert list1.size() == 5 && list1.get(0).getIdea() != null;
|
||||
}
|
||||
@ -526,7 +526,6 @@ class LambdaWrapperTest {
|
||||
assert l4.size() == 14 && l4.get(0).getAddressList().size() == 5;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 别名测试
|
||||
*/
|
||||
|
@ -0,0 +1,48 @@
|
||||
package com.github.yulichang.test.join.m;
|
||||
|
||||
import com.github.yulichang.test.join.dto.UserDTO;
|
||||
import com.github.yulichang.test.join.entity.AddressDO;
|
||||
import com.github.yulichang.test.join.entity.UserDO;
|
||||
import com.github.yulichang.test.join.mapper.UserMapper;
|
||||
import com.github.yulichang.test.util.Reset;
|
||||
import com.github.yulichang.test.util.ThreadLocalUtils;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import lombok.SneakyThrows;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@SpringBootTest
|
||||
public class StringColumTest {
|
||||
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
Reset.reset();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void stringColum() {
|
||||
ThreadLocalUtils.set("SELECT (SELECT id FROM `user` u WHERE u.id = t.id) id, t.`name` AS PName, t.`name` PName, t.`name`," +
|
||||
" (SELECT id FROM `user` u WHERE u.id = t.id), t1.id AS joina_id, t1.user_id, t1.area_id, t1.tel, " +
|
||||
"t1.address, t1.del FROM `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) WHERE t.del = false AND t1.del = false LIMIT 1");
|
||||
List<UserDTO> l3 = userMapper.selectJoinList(UserDTO.class, new MPJLambdaWrapper<UserDO>()
|
||||
.select("(select id from `user` u where u.id = t.id) id")
|
||||
.select("t.`name` as PName")
|
||||
.select("t.`name` PName")
|
||||
.select("t.`name`")
|
||||
.select("(select id from `user` u where u.id = t.id) ")
|
||||
.selectAssociation(AddressDO.class, UserDTO::getAddressDTO)
|
||||
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
|
||||
.last("limit 1"));
|
||||
assert l3.get(0).getPName() != null;
|
||||
l3.forEach(System.out::println);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user