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
beffa8880a
commit
4426d1787b
@ -33,8 +33,10 @@ import javax.sql.DataSource;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* springboot 自动配置类
|
||||||
|
*
|
||||||
* @author yulichang
|
* @author yulichang
|
||||||
* @since 1.3.2
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ -5,8 +5,10 @@ import lombok.experimental.Accessors;
|
|||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 配置类
|
||||||
|
*
|
||||||
* @author yulichang
|
* @author yulichang
|
||||||
* @since 1.3.2
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--suppress VulnerableLibrariesLocal -->
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
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">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
@ -209,8 +209,15 @@ public class MPJInterceptor implements Interceptor {
|
|||||||
//移除result中不存在的标签
|
//移除result中不存在的标签
|
||||||
resultMappings.removeIf(i -> !fieldMap.containsKey(i.getProperty()));
|
resultMappings.removeIf(i -> !fieldMap.containsKey(i.getProperty()));
|
||||||
if (wrapper.isResultMap()) {
|
if (wrapper.isResultMap()) {
|
||||||
List<MybatisLabel<?, ?>> mybatisLabel = wrapper.getResultMapMybatisLabel();
|
buildResult(ms, wrapper.getResultMapMybatisLabel(), columnSet, resultMappings, columnList);
|
||||||
for (MybatisLabel mpjColl : mybatisLabel) {
|
}
|
||||||
|
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();
|
List<Result> list = mpjColl.getResultList();
|
||||||
if (CollectionUtils.isEmpty(list)) {
|
if (CollectionUtils.isEmpty(list)) {
|
||||||
continue;
|
continue;
|
||||||
@ -227,13 +234,21 @@ public class MPJInterceptor implements Interceptor {
|
|||||||
if (r.isId()) {//主键标记为id标签
|
if (r.isId()) {//主键标记为id标签
|
||||||
builder.flags(Collections.singletonList(ResultFlag.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());
|
childMapping.add(builder.build());
|
||||||
}
|
}
|
||||||
String childId = id + StringPool.UNDERSCORE + mpjColl.getEntityClass().getName() + StringPool.UNDERSCORE +
|
//嵌套处理
|
||||||
mpjColl.getOfType().getName() + StringPool.UNDERSCORE + mpjColl.getLabelType() + StringPool.UNDERSCORE +
|
if (CollectionUtils.isNotEmpty(mpjColl.getMybatisLabels())) {
|
||||||
childMapping.stream().map(i -> (CollectionUtils.isEmpty(i.getFlags()) ? ResultFlag.CONSTRUCTOR :
|
this.buildResult(ms, mpjColl.getMybatisLabels(), columnSet, childMapping, columnList);
|
||||||
i.getFlags().get(0)) + i.getProperty() + i.getColumn()).collect(Collectors.joining(StringPool.DASH));
|
}
|
||||||
resultMappings.add(new ResultMapping.Builder(ms.getConfiguration(), mpjColl.getProperty())
|
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())
|
.javaType(mpjColl.getJavaType())
|
||||||
.nestedResultMapId(childId)
|
.nestedResultMapId(childId)
|
||||||
.build());
|
.build());
|
||||||
@ -244,9 +259,6 @@ public class MPJInterceptor implements Interceptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.add(new ResultMap.Builder(ms.getConfiguration(), id, resultType, resultMappings).build());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取字段typeHandle
|
* 获取字段typeHandle
|
||||||
@ -268,12 +280,13 @@ public class MPJInterceptor implements Interceptor {
|
|||||||
* @return 唯一列名
|
* @return 唯一列名
|
||||||
*/
|
*/
|
||||||
private String getColumn(Set<String> pool, String columnName) {
|
private String getColumn(Set<String> pool, String columnName) {
|
||||||
if (!pool.contains(columnName)) {
|
String tagName = StringUtils.getTargetColumn(columnName);
|
||||||
pool.add(columnName);
|
if (!pool.contains(tagName)) {
|
||||||
return columnName;
|
pool.add(tagName);
|
||||||
|
return tagName;
|
||||||
}
|
}
|
||||||
columnName = "mpj_" + StringUtils.getTargetColumn(columnName);
|
tagName = "mpj_" + tagName;
|
||||||
return getColumn(pool, columnName);
|
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.StringUtils;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||||
import com.github.yulichang.exception.MPJException;
|
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.ColumnCache;
|
||||||
import com.github.yulichang.toolkit.support.SelectColumn;
|
import com.github.yulichang.toolkit.support.SelectColumn;
|
||||||
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
||||||
import com.github.yulichang.wrapper.interfaces.LambdaJoin;
|
import com.github.yulichang.wrapper.interfaces.LambdaJoin;
|
||||||
import com.github.yulichang.wrapper.interfaces.Query;
|
import com.github.yulichang.wrapper.interfaces.Query;
|
||||||
import com.github.yulichang.wrapper.interfaces.on.OnFunction;
|
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.MFunc;
|
||||||
import com.github.yulichang.wrapper.resultmap.MybatisLabel;
|
import com.github.yulichang.wrapper.resultmap.MybatisLabel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@ -182,13 +184,13 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
|||||||
MybatisLabel.Builder<C, Z> builder;
|
MybatisLabel.Builder<C, Z> builder;
|
||||||
if (genericType == null || genericType.isAssignableFrom(child)) {
|
if (genericType == null || genericType.isAssignableFrom(child)) {
|
||||||
//找不到集合泛型 List List<?> List<Object> , 直接查询数据库实体
|
//找不到集合泛型 List List<?> List<Object> , 直接查询数据库实体
|
||||||
builder = new MybatisLabel.Builder<>(LabelType.COLLECTION, dtoFieldName, child, field.getType());
|
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType());
|
||||||
} else {
|
} else {
|
||||||
Class<Z> ofType = (Class<Z>) genericType;
|
Class<Z> ofType = (Class<Z>) genericType;
|
||||||
if (ReflectionKit.isPrimitiveOrWrapper(ofType)) {
|
if (ReflectionKit.isPrimitiveOrWrapper(ofType)) {
|
||||||
throw new MPJException("collection 不支持基本数据类型");
|
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());
|
this.resultMapMybatisLabel.add(builder.build());
|
||||||
return typedThis;
|
return typedThis;
|
||||||
@ -231,7 +233,7 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
|||||||
//获取集合泛型
|
//获取集合泛型
|
||||||
Class<?> genericType = ReflectionKit.getGenericType(field);
|
Class<?> genericType = ReflectionKit.getGenericType(field);
|
||||||
Class<Z> ofType = (Class<Z>) genericType;
|
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());
|
this.resultMapMybatisLabel.add(collection.apply(builder).build());
|
||||||
return typedThis;
|
return typedThis;
|
||||||
}
|
}
|
||||||
@ -252,7 +254,7 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
|||||||
}
|
}
|
||||||
this.resultMap = true;
|
this.resultMap = true;
|
||||||
MybatisLabel.Builder<C, F> builder;
|
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());
|
this.resultMapMybatisLabel.add(builder.build());
|
||||||
return typedThis;
|
return typedThis;
|
||||||
}
|
}
|
||||||
@ -272,7 +274,7 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
|||||||
if (ReflectionKit.isPrimitiveOrWrapper(field.getType())) {
|
if (ReflectionKit.isPrimitiveOrWrapper(field.getType())) {
|
||||||
throw new MPJException("association 不支持基本数据类型");
|
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());
|
this.resultMapMybatisLabel.add(collection.apply(builder).build());
|
||||||
return typedThis;
|
return typedThis;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
package com.github.yulichang.wrapper.resultmap;
|
|
||||||
|
|
||||||
public enum LabelType {
|
|
||||||
COLLECTION, ASSOCIATION
|
|
||||||
}
|
|
@ -3,12 +3,17 @@ package com.github.yulichang.wrapper.resultmap;
|
|||||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
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.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 com.github.yulichang.toolkit.ReflectionKit;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -23,8 +28,6 @@ import java.util.stream.Collectors;
|
|||||||
@Getter
|
@Getter
|
||||||
public class MybatisLabel<E, T> {
|
public class MybatisLabel<E, T> {
|
||||||
|
|
||||||
private LabelType labelType;
|
|
||||||
|
|
||||||
private String property;
|
private String property;
|
||||||
|
|
||||||
private Class<E> entityClass;
|
private Class<E> entityClass;
|
||||||
@ -35,13 +38,15 @@ public class MybatisLabel<E, T> {
|
|||||||
|
|
||||||
private List<Result> resultList;
|
private List<Result> resultList;
|
||||||
|
|
||||||
//collection嵌套
|
/**
|
||||||
// private List<Collection> collectionList;
|
* wrapper里面的引用
|
||||||
|
*/
|
||||||
|
private List<MybatisLabel<?, ?>> mybatisLabels;
|
||||||
|
|
||||||
private MybatisLabel() {
|
private MybatisLabel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings({"unused", "unchecked"})
|
||||||
public static class Builder<E, T> {
|
public static class Builder<E, T> {
|
||||||
|
|
||||||
private final MybatisLabel<E, T> mybatisLabel;
|
private final MybatisLabel<E, T> mybatisLabel;
|
||||||
@ -50,14 +55,14 @@ public class MybatisLabel<E, T> {
|
|||||||
* 自动构建
|
* 自动构建
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@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<>();
|
this.mybatisLabel = new MybatisLabel<>();
|
||||||
mybatisLabel.labelType = labelType;
|
|
||||||
mybatisLabel.property = property;
|
mybatisLabel.property = property;
|
||||||
mybatisLabel.entityClass = entityClass;
|
mybatisLabel.entityClass = entityClass;
|
||||||
mybatisLabel.javaType = javaType;
|
mybatisLabel.javaType = javaType;
|
||||||
mybatisLabel.ofType = (Class<T>) entityClass;
|
mybatisLabel.ofType = (Class<T>) entityClass;
|
||||||
mybatisLabel.resultList = new ArrayList<>();
|
mybatisLabel.resultList = new ArrayList<>();
|
||||||
|
mybatisLabel.mybatisLabels = new ArrayList<>();
|
||||||
autoBuild(true, entityClass, (Class<T>) entityClass);
|
autoBuild(true, entityClass, (Class<T>) entityClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,14 +75,14 @@ public class MybatisLabel<E, T> {
|
|||||||
* @param ofType 映射类
|
* @param ofType 映射类
|
||||||
* @param auto 自动映射数据库实体对应的字段
|
* @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<>();
|
this.mybatisLabel = new MybatisLabel<>();
|
||||||
mybatisLabel.labelType = labelType;
|
|
||||||
mybatisLabel.property = property;
|
mybatisLabel.property = property;
|
||||||
mybatisLabel.entityClass = entityClass;
|
mybatisLabel.entityClass = entityClass;
|
||||||
mybatisLabel.javaType = javaType;
|
mybatisLabel.javaType = javaType;
|
||||||
mybatisLabel.ofType = ofType;
|
mybatisLabel.ofType = ofType;
|
||||||
mybatisLabel.resultList = new ArrayList<>();
|
mybatisLabel.resultList = new ArrayList<>();
|
||||||
|
mybatisLabel.mybatisLabels = new ArrayList<>();
|
||||||
autoBuild(auto, entityClass, ofType);
|
autoBuild(auto, entityClass, ofType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +114,85 @@ public class MybatisLabel<E, T> {
|
|||||||
return this;
|
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() {
|
public MybatisLabel<E, T> build() {
|
||||||
|
if (CollectionUtils.isEmpty(mybatisLabel.resultList)) {
|
||||||
|
autoBuild(true, mybatisLabel.entityClass, mybatisLabel.ofType);
|
||||||
|
}
|
||||||
return mybatisLabel;
|
return mybatisLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,6 +203,7 @@ public class MybatisLabel<E, T> {
|
|||||||
Function<TableFieldInfo, Result> build = field -> {
|
Function<TableFieldInfo, Result> build = field -> {
|
||||||
Result result = new Result();
|
Result result = new Result();
|
||||||
result.setId(false);
|
result.setId(false);
|
||||||
|
result.setTableFieldInfo(field);
|
||||||
result.setColumn(field.getColumn());
|
result.setColumn(field.getColumn());
|
||||||
result.setProperty(field.getProperty());
|
result.setProperty(field.getProperty());
|
||||||
result.setJavaType(field.getField().getType());
|
result.setJavaType(field.getField().getType());
|
||||||
|
@ -83,6 +83,11 @@
|
|||||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||||
<version>1.4.5</version>
|
<version>1.4.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
<version>2.14.0</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.github.yulichang.test.dto;
|
||||||
|
|
||||||
|
import com.github.yulichang.test.entity.AreaDO;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AddressDTO {
|
||||||
|
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
private Integer areaId;
|
||||||
|
|
||||||
|
private String tel;
|
||||||
|
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
private Boolean del;
|
||||||
|
|
||||||
|
private List<AreaDO> areaList;
|
||||||
|
|
||||||
|
private AreaDO area;
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.github.yulichang.test.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@ToString
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@TableName("area")
|
||||||
|
public class AreaDTO {
|
||||||
|
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private String province;
|
||||||
|
|
||||||
|
private String city;
|
||||||
|
|
||||||
|
private String area;
|
||||||
|
|
||||||
|
private String postcode;
|
||||||
|
|
||||||
|
private Boolean del;
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
package com.github.yulichang.test.dto;
|
package com.github.yulichang.test.dto;
|
||||||
|
|
||||||
import com.github.yulichang.test.entity.AddressDO;
|
|
||||||
import com.github.yulichang.test.enums.Sex;
|
import com.github.yulichang.test.enums.Sex;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,7 +17,7 @@ public class UserDTO {
|
|||||||
/** user */
|
/** user */
|
||||||
private Integer id;
|
private Integer id;
|
||||||
/** user */
|
/** user */
|
||||||
private String nameName;
|
private Map<String,String> name;
|
||||||
/** user */
|
/** user */
|
||||||
private Sex sex;
|
private Sex sex;
|
||||||
/** user */
|
/** user */
|
||||||
@ -37,5 +37,5 @@ public class UserDTO {
|
|||||||
/** area */
|
/** area */
|
||||||
private String area;
|
private String area;
|
||||||
|
|
||||||
private List<AddressDO> addressList;
|
private List<AddressDTO> addressList;
|
||||||
}
|
}
|
||||||
|
@ -4,24 +4,27 @@ import com.baomidou.mybatisplus.annotation.TableField;
|
|||||||
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.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||||
import com.github.yulichang.test.enums.Sex;
|
import com.github.yulichang.test.enums.Sex;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ToString
|
@ToString
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
@TableName("`user`")
|
@TableName(value = "`user`",autoResultMap = true)
|
||||||
public class UserDO {
|
public class UserDO {
|
||||||
|
|
||||||
@TableId
|
@TableId
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
@TableField("name")
|
@TableField(value = "`name`", typeHandler = JacksonTypeHandler.class)
|
||||||
private String sdafrrvnbioiure;
|
private Map<String,String> name;
|
||||||
|
|
||||||
private Sex sex;
|
private Sex sex;
|
||||||
|
|
||||||
|
@ -29,28 +29,28 @@ INSERT INTO area (id, province, city, area, postcode, del) VALUES (10022, '北
|
|||||||
|
|
||||||
DELETE FROM `user`;
|
DELETE FROM `user`;
|
||||||
|
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 1, '张三01', 1, 1, 'https://url-01', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 1, '{"aa":"aaa","bb":"bbb"}', 1, 1, 'https://url-01', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 2, '李四02', 1, 0, 'https://url-02', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 2, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-02', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 3, '李四02', 1, 0, 'https://url-03', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 3, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-03', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 4, '李四04', 1, 0, 'https://url-04', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 4, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-04', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 5, '李四05', 1, 0, 'https://url-05', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 5, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-05', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 6, '李四06', 1, 0, 'https://url-06', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 6, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-06', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 7, '李四07', 1, 0, 'https://url-07', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 7, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-07', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 8, '李四08', 1, 0, 'https://url-08', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 8, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-08', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 9, '李四09', 1, 0, 'https://url-09', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES ( 9, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-09', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (10, '李四10', 1, 0, 'https://url-10', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (10, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-10', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (11, '李四11', 1, 0, 'https://url-11', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (11, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-11', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (12, '李四12', 1, 0, 'https://url-12', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (12, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-12', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (13, '李四13', 1, 0, 'https://url-13', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (13, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-13', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (14, '李四14', 1, 0, 'https://url-14', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (14, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-14', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (15, '李四15', 1, 0, 'https://url-15', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (15, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-15', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (16, '李四16', 1, 0, 'https://url-16', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (16, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-16', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (17, '李四17', 1, 0, 'https://url-17', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (17, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-17', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (18, '李四18', 1, 0, 'https://url-18', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (18, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-18', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (19, '李四19', 1, 0, 'https://url-19', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (19, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-19', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (20, '李四20', 1, 0, 'https://url-20', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (20, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-20', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (21, '李四21', 1, 0, 'https://url-21', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (21, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-21', false);
|
||||||
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (22, '李四22', 1, 0, 'https://url-22', false);
|
INSERT INTO `user` (id, `name`, `address_id`, sex, head_img, del) VALUES (22, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-22', false);
|
||||||
|
|
||||||
|
|
||||||
DELETE FROM address;
|
DELETE FROM address;
|
||||||
|
@ -2,6 +2,7 @@ package com.github.yulichang.test;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.github.yulichang.test.dto.AddressDTO;
|
||||||
import com.github.yulichang.test.dto.UserDTO;
|
import com.github.yulichang.test.dto.UserDTO;
|
||||||
import com.github.yulichang.test.entity.AddressDO;
|
import com.github.yulichang.test.entity.AddressDO;
|
||||||
import com.github.yulichang.test.entity.AreaDO;
|
import com.github.yulichang.test.entity.AreaDO;
|
||||||
@ -27,7 +28,7 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
class JoinTest {
|
class LambdaWrapperTest {
|
||||||
@Resource
|
@Resource
|
||||||
private UserMapper userMapper;
|
private UserMapper userMapper;
|
||||||
@Resource
|
@Resource
|
||||||
@ -40,10 +41,11 @@ class JoinTest {
|
|||||||
void testJoin() {
|
void testJoin() {
|
||||||
MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
|
MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
|
||||||
.selectAll(UserDO.class)
|
.selectAll(UserDO.class)
|
||||||
.selectCollection(AddressDO.class, UserDTO::getAddressList)
|
.selectCollection(AddressDO.class, UserDTO::getAddressList, addr -> addr
|
||||||
|
.association(AreaDO.class, AddressDTO::getArea))
|
||||||
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
|
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
|
||||||
|
.leftJoin(AreaDO.class, AreaDO::getId, AddressDO::getAreaId)
|
||||||
.orderByDesc(UserDO::getId);
|
.orderByDesc(UserDO::getId);
|
||||||
|
|
||||||
List<UserDTO> list = userMapper.selectJoinList(UserDTO.class, wrapper);
|
List<UserDTO> list = userMapper.selectJoinList(UserDTO.class, wrapper);
|
||||||
list.forEach(System.out::println);
|
list.forEach(System.out::println);
|
||||||
}
|
}
|
@ -1,37 +0,0 @@
|
|||||||
package com.github.yulichang.test;
|
|
||||||
|
|
||||||
import com.github.yulichang.test.mapper.UserMapper;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试
|
|
||||||
*/
|
|
||||||
@SpringBootTest
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
class MPJ131Test {
|
|
||||||
@Resource
|
|
||||||
private UserMapper userMapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 先明确 你要干啥?
|
|
||||||
* 在mapper中定义lambda形式的resultMap?
|
|
||||||
* 要解决问题
|
|
||||||
* 1、只初始化了部分数据库实体类? NPE
|
|
||||||
* <p>
|
|
||||||
* stater
|
|
||||||
* core
|
|
||||||
* anntion
|
|
||||||
* test
|
|
||||||
* <p>
|
|
||||||
* 超高自由度的sql拼接器?
|
|
||||||
* 解决了自连接和子查询和各种函数
|
|
||||||
* 如果底层调用MPJLambdaWrapper那样还有什么意义
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void testJoin() {
|
|
||||||
System.out.println(1);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user