mirror of
https://gitee.com/best_handsome/mybatis-plus-join
synced 2025-07-11 00:02:22 +08:00
对一和对多支持嵌套
This commit is contained in:
parent
e6b8f2547f
commit
eba38a0184
@ -209,45 +209,57 @@ public class MPJInterceptor implements Interceptor {
|
||||
//移除result中不存在的标签
|
||||
resultMappings.removeIf(i -> !fieldMap.containsKey(i.getProperty()));
|
||||
if (wrapper.isResultMap()) {
|
||||
List<MybatisLabel<?, ?>> mybatisLabel = wrapper.getResultMapMybatisLabel();
|
||||
for (MybatisLabel mpjColl : mybatisLabel) {
|
||||
List<Result> list = mpjColl.getResultList();
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
continue;
|
||||
}
|
||||
List<ResultMapping> childMapping = new ArrayList<>(list.size());
|
||||
for (Result r : list) {
|
||||
String columnName = r.getColumn();
|
||||
//列名去重
|
||||
columnName = getColumn(columnSet, columnName);
|
||||
columnList.add(SelectColumn.of(mpjColl.getEntityClass(), r.getColumn(), null,
|
||||
Objects.equals(columnName, r.getColumn()) ? null : columnName, null, null, true, null));
|
||||
ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), r.getProperty(),
|
||||
StringUtils.getTargetColumn(columnName), r.getJavaType());
|
||||
if (r.isId()) {//主键标记为id标签
|
||||
builder.flags(Collections.singletonList(ResultFlag.ID));
|
||||
}
|
||||
childMapping.add(builder.build());
|
||||
}
|
||||
String childId = id + StringPool.UNDERSCORE + mpjColl.getEntityClass().getName() + StringPool.UNDERSCORE +
|
||||
mpjColl.getOfType().getName() + StringPool.UNDERSCORE + mpjColl.getLabelType() + StringPool.UNDERSCORE +
|
||||
childMapping.stream().map(i -> (CollectionUtils.isEmpty(i.getFlags()) ? ResultFlag.CONSTRUCTOR :
|
||||
i.getFlags().get(0)) + i.getProperty() + i.getColumn()).collect(Collectors.joining(StringPool.DASH));
|
||||
resultMappings.add(new ResultMapping.Builder(ms.getConfiguration(), mpjColl.getProperty())
|
||||
.javaType(mpjColl.getJavaType())
|
||||
.nestedResultMapId(childId)
|
||||
.build());
|
||||
//双检
|
||||
if (!ms.getConfiguration().getResultMapNames().contains(childId)) {
|
||||
ResultMap build = new ResultMap.Builder(ms.getConfiguration(), childId, mpjColl.getOfType(), childMapping).build();
|
||||
MPJInterceptor.addResultMap(ms, childId, build);
|
||||
}
|
||||
}
|
||||
buildResult(ms, wrapper.getResultMapMybatisLabel(), columnSet, resultMappings, columnList);
|
||||
}
|
||||
result.add(new ResultMap.Builder(ms.getConfiguration(), id, resultType, resultMappings).build());
|
||||
return result;
|
||||
}
|
||||
|
||||
private void buildResult(MappedStatement ms, List<MybatisLabel<?, ?>> mybatisLabel, Set<String> columnSet,
|
||||
List<ResultMapping> parentMappings, List<SelectColumn> columnList) {
|
||||
for (MybatisLabel<?, ?> mpjColl : mybatisLabel) {
|
||||
List<Result> list = mpjColl.getResultList();
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
continue;
|
||||
}
|
||||
List<ResultMapping> childMapping = new ArrayList<>(list.size());
|
||||
for (Result r : list) {
|
||||
String columnName = r.getColumn();
|
||||
//列名去重
|
||||
columnName = getColumn(columnSet, columnName);
|
||||
columnList.add(SelectColumn.of(mpjColl.getEntityClass(), r.getColumn(), null,
|
||||
Objects.equals(columnName, r.getColumn()) ? null : columnName, null, null, true, null));
|
||||
ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), r.getProperty(),
|
||||
StringUtils.getTargetColumn(columnName), r.getJavaType());
|
||||
if (r.isId()) {//主键标记为id标签
|
||||
builder.flags(Collections.singletonList(ResultFlag.ID));
|
||||
}
|
||||
//TypeHandle
|
||||
TableFieldInfo info = r.getTableFieldInfo();
|
||||
if (info != null && info.getTypeHandler() != null && info.getTypeHandler() != UnknownTypeHandler.class) {
|
||||
builder.typeHandler(getTypeHandler(ms, info));
|
||||
}
|
||||
childMapping.add(builder.build());
|
||||
}
|
||||
//嵌套处理
|
||||
if (CollectionUtils.isNotEmpty(mpjColl.getMybatisLabels())) {
|
||||
this.buildResult(ms, mpjColl.getMybatisLabels(), columnSet, childMapping, columnList);
|
||||
}
|
||||
String childId = "MPJ_" + mpjColl.getEntityClass().getName() + StringPool.UNDERSCORE + mpjColl.getOfType().getName() +
|
||||
StringPool.UNDERSCORE + childMapping.stream().map(i -> (CollectionUtils.isEmpty(i.getFlags()) ?
|
||||
ResultFlag.CONSTRUCTOR : i.getFlags().get(0)) + i.getProperty() + i.getColumn()).collect(Collectors.joining(StringPool.DASH));
|
||||
parentMappings.add(new ResultMapping.Builder(ms.getConfiguration(), mpjColl.getProperty())
|
||||
.javaType(mpjColl.getJavaType())
|
||||
.nestedResultMapId(childId)
|
||||
.build());
|
||||
//双检
|
||||
if (!ms.getConfiguration().getResultMapNames().contains(childId)) {
|
||||
ResultMap build = new ResultMap.Builder(ms.getConfiguration(), childId, mpjColl.getOfType(), childMapping).build();
|
||||
MPJInterceptor.addResultMap(ms, childId, build);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字段typeHandle
|
||||
*/
|
||||
@ -268,12 +280,13 @@ public class MPJInterceptor implements Interceptor {
|
||||
* @return 唯一列名
|
||||
*/
|
||||
private String getColumn(Set<String> pool, String columnName) {
|
||||
if (!pool.contains(columnName)) {
|
||||
pool.add(columnName);
|
||||
return columnName;
|
||||
String tagName = StringUtils.getTargetColumn(columnName);
|
||||
if (!pool.contains(tagName)) {
|
||||
pool.add(tagName);
|
||||
return tagName;
|
||||
}
|
||||
columnName = "mpj_" + StringUtils.getTargetColumn(columnName);
|
||||
return getColumn(pool, columnName);
|
||||
tagName = "mpj_" + tagName;
|
||||
return getColumn(pool, tagName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -11,14 +11,16 @@ import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.exception.MPJException;
|
||||
import com.github.yulichang.toolkit.*;
|
||||
import com.github.yulichang.toolkit.Constant;
|
||||
import com.github.yulichang.toolkit.LambdaUtils;
|
||||
import com.github.yulichang.toolkit.MPJWrappers;
|
||||
import com.github.yulichang.toolkit.ReflectionKit;
|
||||
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||
import com.github.yulichang.toolkit.support.SelectColumn;
|
||||
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
||||
import com.github.yulichang.wrapper.interfaces.LambdaJoin;
|
||||
import com.github.yulichang.wrapper.interfaces.Query;
|
||||
import com.github.yulichang.wrapper.interfaces.on.OnFunction;
|
||||
import com.github.yulichang.wrapper.resultmap.LabelType;
|
||||
import com.github.yulichang.wrapper.resultmap.MFunc;
|
||||
import com.github.yulichang.wrapper.resultmap.MybatisLabel;
|
||||
import lombok.Getter;
|
||||
@ -182,13 +184,13 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
||||
MybatisLabel.Builder<C, Z> builder;
|
||||
if (genericType == null || genericType.isAssignableFrom(child)) {
|
||||
//找不到集合泛型 List List<?> List<Object> , 直接查询数据库实体
|
||||
builder = new MybatisLabel.Builder<>(LabelType.COLLECTION, dtoFieldName, child, field.getType());
|
||||
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType());
|
||||
} else {
|
||||
Class<Z> ofType = (Class<Z>) genericType;
|
||||
if (ReflectionKit.isPrimitiveOrWrapper(ofType)) {
|
||||
throw new MPJException("collection 不支持基本数据类型");
|
||||
}
|
||||
builder = new MybatisLabel.Builder<>(LabelType.COLLECTION, dtoFieldName, child, field.getType(), ofType, true);
|
||||
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), ofType, true);
|
||||
}
|
||||
this.resultMapMybatisLabel.add(builder.build());
|
||||
return typedThis;
|
||||
@ -231,7 +233,7 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
||||
//获取集合泛型
|
||||
Class<?> genericType = ReflectionKit.getGenericType(field);
|
||||
Class<Z> ofType = (Class<Z>) genericType;
|
||||
MybatisLabel.Builder<C, Z> builder = new MybatisLabel.Builder<>(LabelType.COLLECTION, dtoFieldName, child, field.getType(), ofType, false);
|
||||
MybatisLabel.Builder<C, Z> builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), ofType, false);
|
||||
this.resultMapMybatisLabel.add(collection.apply(builder).build());
|
||||
return typedThis;
|
||||
}
|
||||
@ -252,7 +254,7 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
||||
}
|
||||
this.resultMap = true;
|
||||
MybatisLabel.Builder<C, F> builder;
|
||||
builder = new MybatisLabel.Builder<>(LabelType.ASSOCIATION, dtoFieldName, child, field.getType(), (Class<F>) field.getType(), true);
|
||||
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<F>) field.getType(), true);
|
||||
this.resultMapMybatisLabel.add(builder.build());
|
||||
return typedThis;
|
||||
}
|
||||
@ -272,7 +274,7 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
||||
if (ReflectionKit.isPrimitiveOrWrapper(field.getType())) {
|
||||
throw new MPJException("association 不支持基本数据类型");
|
||||
}
|
||||
MybatisLabel.Builder<C, F> builder = new MybatisLabel.Builder<>(LabelType.ASSOCIATION, dtoFieldName, child, field.getType(), (Class<F>) child, false);
|
||||
MybatisLabel.Builder<C, F> builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<F>) child, false);
|
||||
this.resultMapMybatisLabel.add(collection.apply(builder).build());
|
||||
return typedThis;
|
||||
}
|
||||
@ -420,4 +422,4 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package com.github.yulichang.wrapper.resultmap;
|
||||
|
||||
public enum LabelType {
|
||||
COLLECTION, ASSOCIATION
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package com.github.yulichang.wrapper.resultmap;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.apache.ibatis.mapping.ResultMap;
|
||||
|
||||
public class MPJResultMap {
|
||||
|
||||
@Getter
|
||||
private ResultMap resultMap;
|
||||
|
||||
|
||||
}
|
@ -3,12 +3,17 @@ package com.github.yulichang.wrapper.resultmap;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.exception.MPJException;
|
||||
import com.github.yulichang.toolkit.LambdaUtils;
|
||||
import com.github.yulichang.toolkit.ReflectionKit;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
@ -23,8 +28,6 @@ import java.util.stream.Collectors;
|
||||
@Getter
|
||||
public class MybatisLabel<E, T> {
|
||||
|
||||
private LabelType labelType;
|
||||
|
||||
private String property;
|
||||
|
||||
private Class<E> entityClass;
|
||||
@ -35,13 +38,15 @@ public class MybatisLabel<E, T> {
|
||||
|
||||
private List<Result> resultList;
|
||||
|
||||
//collection嵌套
|
||||
// private List<Collection> collectionList;
|
||||
/**
|
||||
* wrapper里面的引用
|
||||
*/
|
||||
private List<MybatisLabel<?, ?>> mybatisLabels;
|
||||
|
||||
private MybatisLabel() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@SuppressWarnings({"unused", "unchecked"})
|
||||
public static class Builder<E, T> {
|
||||
|
||||
private final MybatisLabel<E, T> mybatisLabel;
|
||||
@ -50,14 +55,14 @@ public class MybatisLabel<E, T> {
|
||||
* 自动构建
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Builder(LabelType labelType, String property, Class<E> entityClass, Class<?> javaType) {
|
||||
public Builder(String property, Class<E> entityClass, Class<?> javaType) {
|
||||
this.mybatisLabel = new MybatisLabel<>();
|
||||
mybatisLabel.labelType = labelType;
|
||||
mybatisLabel.property = property;
|
||||
mybatisLabel.entityClass = entityClass;
|
||||
mybatisLabel.javaType = javaType;
|
||||
mybatisLabel.ofType = (Class<T>) entityClass;
|
||||
mybatisLabel.resultList = new ArrayList<>();
|
||||
mybatisLabel.mybatisLabels = new ArrayList<>();
|
||||
autoBuild(true, entityClass, (Class<T>) entityClass);
|
||||
}
|
||||
|
||||
@ -70,14 +75,14 @@ public class MybatisLabel<E, T> {
|
||||
* @param ofType 映射类
|
||||
* @param auto 自动映射数据库实体对应的字段
|
||||
*/
|
||||
public Builder(LabelType labelType, String property, Class<E> entityClass, Class<?> javaType, Class<T> ofType, boolean auto) {
|
||||
public Builder(String property, Class<E> entityClass, Class<?> javaType, Class<T> ofType, boolean auto) {
|
||||
this.mybatisLabel = new MybatisLabel<>();
|
||||
mybatisLabel.labelType = labelType;
|
||||
mybatisLabel.property = property;
|
||||
mybatisLabel.entityClass = entityClass;
|
||||
mybatisLabel.javaType = javaType;
|
||||
mybatisLabel.ofType = ofType;
|
||||
mybatisLabel.resultList = new ArrayList<>();
|
||||
mybatisLabel.mybatisLabels = new ArrayList<>();
|
||||
autoBuild(auto, entityClass, ofType);
|
||||
}
|
||||
|
||||
@ -109,7 +114,85 @@ public class MybatisLabel<E, T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 嵌套
|
||||
*/
|
||||
public <A, R, B extends Collection<R>> Builder<E, T> collection(Class<A> entityClass, SFunction<T, B> func) {
|
||||
String dtoFieldName = LambdaUtils.getName(func);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||
Map<String, Field> fieldMap = ReflectionKit.getFieldMap(dtoClass);
|
||||
Field field = fieldMap.get(dtoFieldName);
|
||||
Class<?> genericType = ReflectionKit.getGenericType(field);
|
||||
MybatisLabel.Builder<A, R> builder;
|
||||
if (genericType == null || genericType.isAssignableFrom(entityClass)) {
|
||||
//找不到集合泛型 List List<?> List<Object> , 直接查询数据库实体
|
||||
builder = new Builder<>(dtoFieldName, entityClass, field.getType());
|
||||
} else {
|
||||
Class<R> ofType = (Class<R>) genericType;
|
||||
if (ReflectionKit.isPrimitiveOrWrapper(ofType)) {
|
||||
throw new MPJException("collection 不支持基本数据类型");
|
||||
}
|
||||
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(Class<A> entityClass, SFunction<T, B> func, MFunc<Builder<A, R>> mFunc) {
|
||||
String dtoFieldName = LambdaUtils.getName(func);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||
Field field = ReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
//获取集合泛型
|
||||
Class<?> genericType = ReflectionKit.getGenericType(field);
|
||||
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<E, T> association(Class<A> child, SFunction<T, B> dtoField) {
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
Map<String, Field> fieldMap = ReflectionKit.getFieldMap(dtoClass);
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Field field = fieldMap.get(dtoFieldName);
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
if (ReflectionKit.isPrimitiveOrWrapper(field.getType())) {
|
||||
throw new MPJException("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<E, T> selectAssociation(Class<A> child, SFunction<T, B> dtoField,
|
||||
MFunc<MybatisLabel.Builder<A, B>> collection) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
Field field = ReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
if (ReflectionKit.isPrimitiveOrWrapper(field.getType())) {
|
||||
throw new MPJException("association 不支持基本数据类型");
|
||||
}
|
||||
MybatisLabel.Builder<A, B> builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<B>) child, false);
|
||||
mybatisLabel.mybatisLabels.add(collection.apply(builder).build());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public MybatisLabel<E, T> build() {
|
||||
if (CollectionUtils.isEmpty(mybatisLabel.resultList)) {
|
||||
autoBuild(true, mybatisLabel.entityClass, mybatisLabel.ofType);
|
||||
}
|
||||
return mybatisLabel;
|
||||
}
|
||||
|
||||
@ -120,6 +203,7 @@ public class MybatisLabel<E, T> {
|
||||
Function<TableFieldInfo, Result> build = field -> {
|
||||
Result result = new Result();
|
||||
result.setId(false);
|
||||
result.setTableFieldInfo(field);
|
||||
result.setColumn(field.getColumn());
|
||||
result.setProperty(field.getProperty());
|
||||
result.setJavaType(field.getField().getType());
|
||||
@ -151,4 +235,4 @@ public class MybatisLabel<E, T> {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user