添加不限制类型的映射方法

This commit is contained in:
yulichang 2023-03-16 19:13:24 +08:00
parent f46422882d
commit 943c48b801
9 changed files with 389 additions and 23 deletions

View File

@ -10,7 +10,7 @@ import com.github.yulichang.toolkit.Constant;
import com.github.yulichang.toolkit.MPJReflectionKit;
import com.github.yulichang.toolkit.TableHelper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.github.yulichang.wrapper.resultmap.MybatisLabel;
import com.github.yulichang.wrapper.resultmap.Label;
import com.github.yulichang.wrapper.resultmap.Result;
import com.github.yulichang.wrapper.segments.Select;
import com.github.yulichang.wrapper.segments.SelectLabel;
@ -190,7 +190,7 @@ public class MPJInterceptor implements Interceptor {
}
if (wrapper.isResultMap()) {
for (Object o : wrapper.getResultMapMybatisLabel()) {
MybatisLabel<?, ?> label = (MybatisLabel<?, ?>) o;
Label<?> label = (Label<?>) o;
resultMappings.add(buildResult(ms, label, columnSet, columnList));
}
}
@ -214,15 +214,13 @@ public class MPJInterceptor implements Interceptor {
/**
* @return 返回节点id
*/
private ResultMapping buildResult(MappedStatement ms, MybatisLabel<?, ?> mybatisLabel, Set<String> columnSet,
private ResultMapping buildResult(MappedStatement ms, Label<?> mybatisLabel, Set<String> columnSet,
List<Select> columnList) {
List<Result> resultList = mybatisLabel.getResultList();
if (CollectionUtils.isEmpty(resultList)) {
return null;
}
StringBuilder childId = new StringBuilder("MPJ_")
.append(mybatisLabel.getEntityClass().getName())
.append(StringPool.UNDERSCORE)
.append(mybatisLabel.getOfType().getName())
.append(StringPool.UNDERSCORE)
.append(mybatisLabel.getProperty())
@ -235,7 +233,7 @@ public class MPJInterceptor implements Interceptor {
String columnName = StringUtils.getTargetColumn(r.getSelectNormal().getColumn());
SelectLabel label;
Field field = ofTypeField.get(r.getProperty());
String index = mybatisLabel.getIndex();
String index = r.getIndex();
if (columnSet.contains(columnName)) {
columnName = getColumn(columnSet, columnName, 0);
label = new SelectLabel(r.getSelectNormal(), null, mybatisLabel.getOfType(), field, columnName, StringUtils.isNotBlank(index), index);
@ -269,7 +267,8 @@ public class MPJInterceptor implements Interceptor {
if (CollectionUtils.isNotEmpty(mybatisLabel.getMybatisLabels())) {
//递归调用
childId.append("[");
for (MybatisLabel<?, ?> o : mybatisLabel.getMybatisLabels()) {
for (Object it : mybatisLabel.getMybatisLabels()) {
Label<?> o = (Label<?>) it;
if (Objects.isNull(o)) {
continue;
}

View File

@ -14,7 +14,7 @@ import com.github.yulichang.wrapper.interfaces.Chain;
import com.github.yulichang.wrapper.interfaces.Query;
import com.github.yulichang.wrapper.interfaces.QueryJoin;
import com.github.yulichang.wrapper.interfaces.QueryLabel;
import com.github.yulichang.wrapper.resultmap.MybatisLabel;
import com.github.yulichang.wrapper.resultmap.Label;
import com.github.yulichang.wrapper.segments.Select;
import com.github.yulichang.wrapper.segments.SelectCache;
import com.github.yulichang.wrapper.segments.SelectNormal;
@ -50,7 +50,7 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
* 映射关系
*/
@Getter
private final List<MybatisLabel<?, ?>> resultMapMybatisLabel = new ArrayList<>();
private final List<Label<?>> resultMapMybatisLabel = new ArrayList<>();
/**
* 是否有表别名
*/
@ -187,7 +187,7 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
}
@Override
public void addLabel(MybatisLabel<?, ?> label) {
public void addLabel(Label<?> label) {
this.resultMap = true;
this.resultMapMybatisLabel.add(label);
}

View File

@ -5,8 +5,10 @@ import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.toolkit.LambdaUtils;
import com.github.yulichang.toolkit.MPJReflectionKit;
import com.github.yulichang.wrapper.resultmap.Label;
import com.github.yulichang.wrapper.resultmap.MFunc;
import com.github.yulichang.wrapper.resultmap.MybatisLabel;
import com.github.yulichang.wrapper.resultmap.MybatisLabelFree;
import java.lang.reflect.Field;
import java.util.Collection;
@ -21,7 +23,7 @@ import java.util.Map;
@SuppressWarnings({"unchecked", "unused"})
public interface QueryLabel<Children> {
void addLabel(MybatisLabel<?, ?> label);
void addLabel(Label<?> label);
Children getChildren();
@ -104,6 +106,21 @@ public interface QueryLabel<Children> {
return selectCollection(null, child, dtoField, collection);
}
default <S, Z, F extends java.util.Collection<Z>> Children selectCollection(SFunction<S, F> dtoField,
MFunc<MybatisLabelFree.Builder<Z>> collection) {
//自由映射必须存在泛型Z
String dtoFieldName = LambdaUtils.getName(dtoField);
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
Field field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
//获取集合泛型
Class<?> genericType = MPJReflectionKit.getGenericType(field);
Class<Z> ofType = (Class<Z>) genericType;
MybatisLabelFree.Builder<Z> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), ofType);
MybatisLabelFree.Builder<Z> czBuilder = collection.apply(builder);
addLabel(czBuilder.build());
return getChildren();
}
default <S, C, Z, F extends java.util.Collection<Z>> Children selectCollection(String prefix,
Class<C> child,
SFunction<S, F> dtoField,
@ -152,6 +169,18 @@ public interface QueryLabel<Children> {
return selectAssociation(null, child, dtoField, collection);
}
default <S, C, F> Children selectAssociation(SFunction<S, F> dtoField,
MFunc<MybatisLabelFree.Builder<F>> collection) {
String dtoFieldName = LambdaUtils.getName(dtoField);
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
Field field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
MybatisLabelFree.Builder<F> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), (Class<F>) field.getType());
MybatisLabelFree.Builder<F> cfBuilder = collection.apply(builder);
addLabel(cfBuilder.build());
return getChildren();
}
default <S, C, F> Children selectAssociation(String prefix, Class<C> child, SFunction<S, F> dtoField,
MFunc<MybatisLabel.Builder<C, F>> collection) {
String dtoFieldName = LambdaUtils.getName(dtoField);

View File

@ -0,0 +1,16 @@
package com.github.yulichang.wrapper.resultmap;
import java.util.List;
public interface Label<T> {
String getProperty();
Class<?> getJavaType();
Class<T> getOfType();
List<Result> getResultList();
List<?> getMybatisLabels();
}

View File

@ -22,7 +22,7 @@ import java.util.stream.Collectors;
* @since 1.3.0
*/
@Getter
public class MybatisLabel<E, T> {
public class MybatisLabel<E, T> implements Label<T> {
private String index;
@ -39,7 +39,7 @@ public class MybatisLabel<E, T> {
/**
* wrapper里面的引用
*/
private List<MybatisLabel<?, ?>> mybatisLabels;
private List<Label<?>> mybatisLabels;
private MybatisLabel() {
}
@ -87,28 +87,28 @@ public class MybatisLabel<E, T> {
}
public Builder<E, T> id(SFunction<E, ?> entity, SFunction<T, ?> tag) {
Result.Builder<E, T> builder = new Result.Builder<>(true);
Result.Builder<T> builder = new Result.Builder<>(true, mybatisLabel.index);
builder.column(entity).property(tag);
mybatisLabel.resultList.add(builder.build());
return this;
}
public Builder<E, T> id(SFunction<E, ?> entity) {
Result.Builder<E, T> builder = new Result.Builder<>(true);
Result.Builder<T> builder = new Result.Builder<>(true, mybatisLabel.index);
builder.column(entity);
mybatisLabel.resultList.add(builder.build());
return this;
}
public Builder<E, T> result(SFunction<E, ?> entity, SFunction<T, ?> tag) {
Result.Builder<E, T> builder = new Result.Builder<>(false);
Result.Builder<T> builder = new Result.Builder<>(false, mybatisLabel.index);
builder.column(entity).property(tag);
mybatisLabel.resultList.add(builder.build());
return this;
}
public Builder<E, T> result(SFunction<E, ?> entity) {
Result.Builder<E, T> builder = new Result.Builder<>(false);
Result.Builder<T> builder = new Result.Builder<>(false, mybatisLabel.index);
builder.column(entity);
mybatisLabel.resultList.add(builder.build());
return this;
@ -143,6 +143,22 @@ public class MybatisLabel<E, T> {
return collection(null, entityClass, func, mFunc);
}
/**
* 嵌套
*/
public <A, R, B extends Collection<R>> Builder<E, T> collection(SFunction<T, B> func,
MFunc<MybatisLabelFree.Builder<R>> mFunc) {
String dtoFieldName = LambdaUtils.getName(func);
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
Field field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
//获取集合泛型
Class<?> genericType = MPJReflectionKit.getGenericType(field);
Class<R> ofType = (Class<R>) genericType;
MybatisLabelFree.Builder<R> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), ofType);
mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build());
return this;
}
/**
* 嵌套
*/
@ -185,6 +201,20 @@ public class MybatisLabel<E, T> {
return association(null, child, dtoField, collection);
}
/**
* 嵌套
*/
public <A, B> Builder<E, T> association(SFunction<T, B> dtoField,
MFunc<MybatisLabelFree.Builder<B>> collection) {
String dtoFieldName = LambdaUtils.getName(dtoField);
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
Field field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
MybatisLabelFree.Builder<B> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), (Class<B>) field.getType());
mybatisLabel.mybatisLabels.add(collection.apply(builder).build());
return this;
}
/**
* 嵌套
*/

View File

@ -0,0 +1,245 @@
package com.github.yulichang.wrapper.resultmap;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.toolkit.LambdaUtils;
import com.github.yulichang.toolkit.MPJReflectionKit;
import com.github.yulichang.toolkit.support.ColumnCache;
import com.github.yulichang.wrapper.segments.SelectCache;
import lombok.Getter;
import java.lang.reflect.Field;
import java.util.*;
/**
* 无泛型约束 实现自由映射
*
* @author yulichang
* @since 1.4.4
*/
@Getter
public class MybatisLabelFree<T> implements Label<T> {
private String property;
private Class<?> javaType;
private Class<T> ofType;
private List<Result> resultList;
/**
* wrapper里面的引用
*/
private List<Label<?>> mybatisLabels;
private MybatisLabelFree() {
}
@SuppressWarnings({"unused", "unchecked", "DuplicatedCode"})
public static class Builder<T> {
private final MybatisLabelFree<T> mybatisLabel;
/**
* 手动构建
*
* @param property property
* @param javaType javaType
* @param ofType 映射类
*/
public Builder(String property, Class<?> javaType, Class<T> ofType) {
this.mybatisLabel = new MybatisLabelFree<>();
mybatisLabel.property = property;
mybatisLabel.javaType = javaType;
mybatisLabel.ofType = ofType;
mybatisLabel.resultList = new ResultList();
mybatisLabel.mybatisLabels = new ArrayList<>();
}
public <E> Builder<T> all(Class<?> entityClass) {
allBuild(null, entityClass);
return this;
}
public <E> Builder<T> all(String prefix, Class<?> entityClass) {
allBuild(prefix, entityClass);
return this;
}
public <E> Builder<T> id(SFunction<E, ?> entity, SFunction<T, ?> tag) {
Result.Builder<T> builder = new Result.Builder<>(true, null);
builder.column(entity).property(tag);
mybatisLabel.resultList.add(builder.build());
return this;
}
public <E> Builder<T> id(SFunction<E, ?> entity) {
Result.Builder<T> builder = new Result.Builder<>(true, null);
builder.column(entity);
mybatisLabel.resultList.add(builder.build());
return this;
}
public <E> Builder<T> id(String index, SFunction<E, ?> entity, SFunction<T, ?> tag) {
Result.Builder<T> builder = new Result.Builder<>(true, index);
builder.column(entity).property(tag);
mybatisLabel.resultList.add(builder.build());
return this;
}
public <E> Builder<T> id(String index, SFunction<E, ?> entity) {
Result.Builder<T> builder = new Result.Builder<>(true, index);
builder.column(entity);
mybatisLabel.resultList.add(builder.build());
return this;
}
public <E> Builder<T> result(SFunction<E, ?> entity, SFunction<T, ?> tag) {
Result.Builder<T> builder = new Result.Builder<>(false, null);
builder.column(entity).property(tag);
mybatisLabel.resultList.add(builder.build());
return this;
}
public <E> Builder<T> result(SFunction<E, ?> entity) {
Result.Builder<T> builder = new Result.Builder<>(false, null);
builder.column(entity);
mybatisLabel.resultList.add(builder.build());
return this;
}
public <E> Builder<T> result(String index, SFunction<E, ?> entity, SFunction<T, ?> tag) {
Result.Builder<T> builder = new Result.Builder<>(false, index);
builder.column(entity).property(tag);
mybatisLabel.resultList.add(builder.build());
return this;
}
public <E> Builder<T> result(String index, SFunction<E, ?> entity) {
Result.Builder<T> builder = new Result.Builder<>(false, index);
builder.column(entity);
mybatisLabel.resultList.add(builder.build());
return this;
}
public <A, R, B extends Collection<R>> Builder<T> collection(Class<A> entityClass, SFunction<T, B> func) {
return collection(null, entityClass, func);
}
/**
* 嵌套
*/
public <A, R, B extends Collection<R>> Builder<T> collection(String prefix, Class<A> entityClass, SFunction<T, B> func) {
String dtoFieldName = LambdaUtils.getName(func);
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
Map<String, Field> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
Field field = fieldMap.get(dtoFieldName);
Class<?> genericType = MPJReflectionKit.getGenericType(field);
MybatisLabel.Builder<A, R> builder;
if (genericType == null || genericType.isAssignableFrom(entityClass)) {
//找不到集合泛型 List List<?> List<Object> 直接查询数据库实体
builder = new MybatisLabel.Builder<>(prefix, dtoFieldName, entityClass, field.getType());
} else {
Class<R> ofType = (Class<R>) genericType;
builder = new MybatisLabel.Builder<>(prefix, dtoFieldName, entityClass, field.getType(), ofType, true);
}
mybatisLabel.mybatisLabels.add(builder.build());
return this;
}
public <A, R, B extends Collection<R>> Builder<T> collection(Class<A> entityClass, SFunction<T, B> func, MFunc<MybatisLabel.Builder<A, R>> mFunc) {
return collection(null, entityClass, func, mFunc);
}
public <A, R, B extends Collection<R>> Builder<T> collection(SFunction<T, B> func,
MFunc<MybatisLabelFree.Builder<R>> mFunc) {
String dtoFieldName = LambdaUtils.getName(func);
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
Field field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
//获取集合泛型
Class<?> genericType = MPJReflectionKit.getGenericType(field);
Class<R> ofType = (Class<R>) genericType;
MybatisLabelFree.Builder<R> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), ofType);
mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build());
return this;
}
/**
* 嵌套
*/
public <A, R, B extends Collection<R>> Builder<T> collection(String prefix,
Class<A> entityClass,
SFunction<T, B> func,
MFunc<MybatisLabel.Builder<A, R>> mFunc) {
String dtoFieldName = LambdaUtils.getName(func);
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
Field field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
//获取集合泛型
Class<?> genericType = MPJReflectionKit.getGenericType(field);
Class<R> ofType = (Class<R>) genericType;
MybatisLabel.Builder<A, R> builder = new MybatisLabel.Builder<>(prefix, dtoFieldName, entityClass, field.getType(), ofType, false);
mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build());
return this;
}
public <A, B> Builder<T> association(Class<A> child, SFunction<T, B> dtoField) {
return association(null, child, dtoField);
}
/**
* 嵌套
*/
public <A, B> Builder<T> association(String index, Class<A> child, SFunction<T, B> dtoField) {
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
Map<String, Field> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
String dtoFieldName = LambdaUtils.getName(dtoField);
Field field = fieldMap.get(dtoFieldName);
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
MybatisLabel.Builder<A, B> builder;
builder = new MybatisLabel.Builder<>(index, dtoFieldName, child, field.getType(), (Class<B>) field.getType(), true);
mybatisLabel.mybatisLabels.add(builder.build());
return this;
}
public <A, B> Builder<T> association(Class<A> child, SFunction<T, B> dtoField,
MFunc<MybatisLabel.Builder<A, B>> collection) {
return association(null, child, dtoField, collection);
}
/**
* 嵌套
*/
public <A, B> Builder<T> association(String index, 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 = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
MybatisLabel.Builder<A, B> builder = new MybatisLabel.Builder<>(index, dtoFieldName, child, field.getType(), (Class<B>) field.getType(), false);
mybatisLabel.mybatisLabels.add(collection.apply(builder).build());
return this;
}
public MybatisLabelFree<T> build() {
return mybatisLabel;
}
private void allBuild(String prefix, Class<?> entityClass) {
Map<String, Field> tagMap = MPJReflectionKit.getFieldMap(mybatisLabel.getOfType());
List<SelectCache> listField = ColumnCache.getListField(entityClass);
for (SelectCache s : listField) {
Field field = tagMap.get(s.getColumProperty());
if (Objects.nonNull(field)) {
Result result = new Result();
result.setIndex(prefix);
result.setId(s.isPk());
result.setJavaType(field.getType());
result.setProperty(s.getColumProperty());
result.setSelectNormal(s);
mybatisLabel.resultList.add(result);
}
}
}
}
}

View File

@ -40,21 +40,22 @@ public class Result {
@SuppressWarnings({"UnusedReturnValue", "unused"})
public static class Builder<E, T> {
public static class Builder<T> {
private final Result result;
public Builder(boolean isId) {
public Builder(boolean isId, String index) {
this.result = new Result();
result.isId = isId;
result.index = index;
}
public Builder<E, T> property(SFunction<T, ?> property) {
public Builder<T> property(SFunction<T, ?> property) {
result.property = LambdaUtils.getName(property);
return this;
}
public Builder<E, T> column(SFunction<E, ?> column) {
public <E> Builder<T> column(SFunction<E, ?> column) {
Class<E> entityClass = LambdaUtils.getEntityClass(column);
Map<String, SelectCache> normalMap = ColumnCache.getMapField(entityClass);
String name = LambdaUtils.getName(column);
@ -72,12 +73,12 @@ public class Result {
return this;
}
public Builder<E, T> javaType(Class<?> javaType) {
public Builder<T> javaType(Class<?> javaType) {
result.javaType = javaType;
return this;
}
public Builder<E, T> jdbcType(JdbcType jdbcType) {
public Builder<T> jdbcType(JdbcType jdbcType) {
result.jdbcType = jdbcType;
return this;
}

View File

@ -0,0 +1,21 @@
package com.github.yulichang.wrapper.resultmap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
public class ResultList extends ArrayList<Result> {
private final Set<String> propertySet = new HashSet<>();
@Override
public boolean add(Result result) {
if (propertySet.contains(result.getProperty())) {
super.removeIf(i -> i.getProperty().equals(result.getProperty()));
} else {
propertySet.add(result.getProperty());
}
return super.add(result);
}
}

View File

@ -847,4 +847,29 @@ class LambdaWrapperTest {
assert list.get(0).getAddressList() != null && list.get(0).getAddressList().get(0).getId() != null;
list.forEach(System.out::println);
}
@Test
void joinRandomMap() {
MPJLambdaWrapper<UserDO> wrapper = JoinWrappers.lambda(UserDO.class)
.logicDelToOn()
.selectAll(UserDO.class)
// .selectCollection(AddressDO.class, UserDTO::getAddressList, addr -> addr
// .id(AddressDO::getId))
.selectCollection(UserDTO::getAddressList, addr -> addr
.id(AddressDO::getId, AddressDTO::getId)
.result(UserDO::getName, AddressDTO::getAddress)
.collection(AddressDTO::getAreaList, map -> map
.id(AreaDO::getId)
.result(AreaDO::getArea, AreaDO::getArea)))
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
.leftJoin(AreaDO.class, AreaDO::getId, AddressDO::getAreaId)
.le(UserDO::getId, 10000)
.orderByDesc(UserDO::getId);
List<UserDTO> list = wrapper.list(UserDTO.class);
System.out.println(list);
assert list.get(0).getAddressList() != null && list.get(0).getAddressList().get(0).getId() != null;
list.forEach(System.out::println);
}
}