支持字段映射

This commit is contained in:
bjdys 2021-08-23 16:37:17 +08:00
parent 2c5772d09d
commit 2659497f0a
26 changed files with 663 additions and 307 deletions

View File

@ -3,7 +3,6 @@ package com.baomidou.mybatisplus.core.metadata;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.github.yulichang.annotation.MPJMapping;
import com.github.yulichang.annotation.MPJMappingApply;
import com.github.yulichang.annotation.MPJMappingCondition;
import lombok.AllArgsConstructor;
@ -36,36 +35,37 @@ public class MPJMappingWrapper {
private final boolean hasLast;
private String last;
public MPJMappingWrapper(MPJMapping mapping) {
this.hasFirst = StringUtils.isNotBlank(mapping.first());
public MPJMappingWrapper(String first, String select, MPJMappingApply[] applys,
MPJMappingCondition[] conditions, String last) {
this.hasFirst = StringUtils.isNotBlank(first);
if (this.hasFirst) {
this.first = mapping.first();
this.first = first;
}
this.hasSelect = StringUtils.isNotBlank(mapping.select());
this.hasSelect = StringUtils.isNotBlank(select);
if (this.hasSelect) {
this.select = mapping.select();
this.select = select;
}
this.hasApply = mapping.apply().length > 0;
this.hasApply = applys.length > 0;
if (this.hasApply) {
this.applyList = new ArrayList<>();
for (MPJMappingApply apply : mapping.apply()) {
for (MPJMappingApply apply : applys) {
this.applyList.add(new Apply(apply.value(), apply.args()));
}
}
this.hasCondition = mapping.condition().length > 0;
this.hasCondition = conditions.length > 0;
if (this.hasCondition) {
this.conditionList = new ArrayList<>();
for (MPJMappingCondition condition : mapping.condition()) {
for (MPJMappingCondition condition : conditions) {
conditionList.add(new Condition(condition.keyWord(), condition.column(), condition.value()));
}
}
this.hasLast = StringUtils.isNotBlank(mapping.last());
this.hasLast = StringUtils.isNotBlank(last);
if (this.hasLast) {
this.last = mapping.last();
this.last = last;
}
}

View File

@ -0,0 +1,61 @@
package com.baomidou.mybatisplus.core.metadata;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.github.yulichang.annotation.MPJTableAlias;
import com.github.yulichang.toolkit.Constant;
import lombok.Data;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 全局表别名控制,默认表别名为 t t1 t2 ... <br>
* 可以通过@MPJTableAlias注解指定表别名<br/>
* 仅对MPJLambdaWrapper有效
*
* @author yulichang
* @see com.github.yulichang.wrapper.MPJLambdaWrapper
* @see MPJTableAlias
* @since 1.2.0
*/
public class MPJTableAliasHelper {
public static final Map<Class<?>, TableAlias> CACHE = new ConcurrentHashMap<>();
/**
* 用于生成别名的序号
*/
private static final AtomicInteger index = new AtomicInteger(1);
public static void init(Class<?> clazz) {
TableAlias alias = new TableAlias();
MPJTableAlias tableAlias = clazz.getAnnotation(MPJTableAlias.class);
if (tableAlias != null && StringUtils.isNotBlank(tableAlias.value())) {
alias.setAlias(tableAlias.value());
} else {
alias.setAlias(Constant.TABLE_ALIAS + index.getAndIncrement());
}
alias.setAliasDOT(alias.getAlias() + StringPool.DOT);
CACHE.put(clazz, alias);
}
public static TableAlias get(Class<?> clazz) {
return CACHE.get(clazz);
}
@Data
public static class TableAlias {
/**
* 表别名
*/
private String alias;
/**
* 前缀
*/
private String aliasDOT;
}
}

View File

@ -1,10 +1,8 @@
package com.baomidou.mybatisplus.core.metadata;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.github.yulichang.annotation.MPJMapping;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.github.yulichang.annotation.EntityMapping;
import com.github.yulichang.annotation.FieldMapping;
import com.github.yulichang.base.MPJBaseMapper;
import com.github.yulichang.exception.MPJException;
import com.github.yulichang.toolkit.SpringContentUtils;
@ -15,6 +13,7 @@ import lombok.ToString;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -31,6 +30,22 @@ import java.util.Map;
@EqualsAndHashCode
public class MPJTableFieldInfo {
/**
* 是否是实体映射
*/
private final boolean isMappingEntity;
/**
* 是否是属性映射
*/
private final boolean isMappingField;
/**
* 字段映射是绑定的字段
*/
private Field bindField;
/**
* 是否移除绑定字段
*/
private final boolean isRemoveBindField;
/**
* 实体类
*/
@ -58,7 +73,7 @@ public class MPJTableFieldInfo {
/**
* 当前类实体属性
*/
private final String thisProperty;
private String thisProperty;
/**
* 当前字段信息
*/
@ -74,7 +89,7 @@ public class MPJTableFieldInfo {
/**
* 映射属性名
*/
private final String joinProperty;
private String joinProperty;
/**
* 映射属性数据库列名
*/
@ -105,33 +120,112 @@ public class MPJTableFieldInfo {
/**
* 初始化关联字段信息
*/
public MPJTableFieldInfo(Class<?> entityType, MPJMapping mapping, Field field) {
public MPJTableFieldInfo(Class<?> entityType, EntityMapping mapping, Field field) {
this.isMappingEntity = true;
this.isMappingField = false;
initField(field);
if (mapping.tag() != Object.class) {
this.joinClass = mapping.tag();
}
this.entityType = entityType;
this.isThrowExp = mapping.isThrowExp();
this.thisMapKey = StringUtils.isBlank(mapping.thisMapKey()) ? null : mapping.thisMapKey();
this.joinMapKey = StringUtils.isBlank(mapping.joinMapKsy()) ? null : mapping.joinMapKsy();
this.wrapper = new MPJMappingWrapper(mapping);
initThisField(mapping.thisMapKey(), mapping.thisField());
initJoinField(mapping.joinMapKey(), mapping.joinField());
this.isRemoveBindField = StringUtils.isNotBlank(mapping.select()) && (!Arrays.asList(mapping.select().split(
StringPool.COMMA)).contains(this.joinColumn.trim()));
this.wrapper = new MPJMappingWrapper(mapping.first(), StringUtils.isBlank(mapping.select()) ? null :
(this.isRemoveBindField ? this.joinColumn + StringPool.COMMA + mapping.select() : mapping.select()),
mapping.apply(), mapping.condition(), mapping.last());
}
public MPJTableFieldInfo(Class<?> entityType, FieldMapping mappingField, Field field) {
this.isMappingEntity = false;
this.isMappingField = true;
field.setAccessible(true);
this.field = field;
this.property = field.getName();
this.isCollection = Collection.class.isAssignableFrom(field.getType());
if (this.isCollection && !List.class.isAssignableFrom(this.field.getType())) {
throw new MPJException("对多关系的数据结构目前只支持 <List> 暂不支持其他Collection实现 " + this.field.getType().getTypeName());
}
if (StringUtils.isNotBlank(mapping.joinField())) {
this.joinProperty = mapping.joinField();
this.joinClass = mappingField.tag();
this.entityType = entityType;
this.isThrowExp = mappingField.isThrowExp();
initThisField(mappingField.thisMapKey(), mappingField.thisField());
initJoinField(mappingField.joinMapKey(), mappingField.joinField());
this.isRemoveBindField = !mappingField.select().equals(this.joinColumn.trim());
this.wrapper = new MPJMappingWrapper(mappingField.first(), this.isRemoveBindField ? this.joinColumn +
StringPool.COMMA + mappingField.select() : mappingField.select(), mappingField.apply(),
mappingField.condition(), mappingField.last());
initBindField(mappingField.select());
}
private void initBindField(String bindName) {
List<Field> fields = ReflectionKit.getFieldList(ClassUtils.getUserClass(this.joinClass));
Field field = fields.stream().filter(f -> f.getName().equals(bindName)).findFirst().orElse(null);
if (field == null) {
throw new MPJException("字段不存在 " + this.joinClass.getName() + " " + bindName);
}
this.bindField = field;
}
private void initJoinField(String joinMapKey, String joinField) {
if (StringUtils.isNotBlank(joinField)) {
this.joinProperty = joinField;
} else {
TableInfo info = getTableInfo(this.joinClass);
Assert.isTrue(info.havePK(), "实体未定义主键 %s ", this.joinClass.getName());
this.joinProperty = info.getKeyProperty();
}
if (StringUtils.isNotBlank(mapping.thisField())) {
this.thisProperty = mapping.thisField();
TableInfo joinTableInfo = getTableInfo(this.joinClass);
TableFieldInfo joinFieldInfo = joinTableInfo.getFieldList().stream().filter(f ->
f.getField().getName().equals(this.joinProperty)).findFirst().orElse(null);
if (joinFieldInfo == null) {
if (joinTableInfo.havePK() && this.joinProperty.equals(joinTableInfo.getKeyProperty())) {
this.joinColumn = joinTableInfo.getKeyColumn();
this.joinField = ReflectionKit.getFieldList(this.joinClass).stream().filter(i ->
i.getName().equals(joinTableInfo.getKeyProperty())).findFirst().orElse(null);
}
} else {
this.joinColumn = joinFieldInfo.getColumn();
this.joinField = joinFieldInfo.getField();
}
Assert.notNull(this.joinField, "MPJMapping注解thisField不存在 %s , %s", this.joinClass.getName(),
StringUtils.isBlank(this.joinProperty) ? "主键" : this.joinProperty);
Assert.notNull(this.joinColumn, "MPJMapping注解thisField不存在 %s , %s", this.joinClass.getName(),
StringUtils.isBlank(this.joinProperty) ? "主键" : this.joinProperty);
this.joinField.setAccessible(true);
this.joinMapKey = StringUtils.isBlank(joinMapKey) ? this.joinColumn : joinMapKey;
}
private void initThisField(String thisMapKey, String thisField) {
if (StringUtils.isNotBlank(thisField)) {
this.thisProperty = thisField;
} else {
TableInfo info = getTableInfo(this.entityType);
Assert.isTrue(info.havePK(), "实体未定义主键 %s ", this.entityType.getName());
this.thisProperty = info.getKeyProperty();
}
TableInfo tableInfo = getTableInfo(this.entityType);
if (tableInfo.havePK() && this.thisProperty.equals(tableInfo.getKeyProperty())) {
this.thisField = ReflectionKit.getFieldList(ClassUtils.getUserClass(entityType)).stream().filter(f ->
f.getName().equals(tableInfo.getKeyProperty())).findFirst().orElse(null);
Assert.notNull(this.thisField, "MPJMapping注解thisField不存在 %s , %s", entityType.getName(),
StringUtils.isBlank(this.thisProperty) ? "主键" : this.thisProperty);
this.thisColumn = tableInfo.getKeyColumn();
} else {
TableFieldInfo fieldInfo = tableInfo.getFieldList().stream().filter(f ->
f.getField().getName().equals(this.thisProperty)).findFirst().orElse(null);
Assert.notNull(fieldInfo, "MPJMapping注解thisField不存在 %s , %s", entityType.getName(),
StringUtils.isBlank(this.thisProperty) ? "主键" : this.thisProperty);
assert fieldInfo != null;
this.thisField = fieldInfo.getField();
this.thisColumn = fieldInfo.getColumn();
}
this.thisField.setAccessible(true);
this.thisMapKey = StringUtils.isBlank(thisMapKey) ? this.thisColumn : thisMapKey;
}
private void initField(Field field) {
@ -139,7 +233,9 @@ public class MPJTableFieldInfo {
this.field = field;
this.property = field.getName();
this.isCollection = Collection.class.isAssignableFrom(field.getType());
if (this.isCollection && !List.class.isAssignableFrom(this.field.getType())) {
throw new MPJException("对多关系的数据结构目前只支持 <List> 暂不支持其他Collection实现 " + this.field.getType().getTypeName());
}
if (Map.class.isAssignableFrom(field.getType())) {
this.fieldIsMap = true;
} else {
@ -156,83 +252,16 @@ public class MPJTableFieldInfo {
}
}
if (List.class.isAssignableFrom(field.getType())) {
if (field.getGenericType() instanceof ParameterizedType) {
ParameterizedType t = (ParameterizedType) field.getGenericType();
this.joinClass = (Class<?>) t.getActualTypeArguments()[0];
}
} else {
this.joinClass = field.getType();
}
}
@SuppressWarnings("ConstantConditions")
public Field getThisField() {
if (this.thisField == null) {
TableInfo tableInfo = getTableInfo(this.entityType);
if (tableInfo.havePK() && this.thisProperty.equals(tableInfo.getKeyProperty())) {
this.thisField = ReflectionKit.getFieldList(ClassUtils.getUserClass(entityType)).stream().filter(f ->
f.getName().equals(tableInfo.getKeyProperty())).findFirst().orElse(null);
Assert.notNull(this.thisField, "MPJMapping注解thisField不存在 %s , %s", entityType.getName(),
StringUtils.isBlank(this.thisProperty) ? "主键" : this.thisProperty);
this.thisColumn = tableInfo.getKeyColumn();
} else {
TableFieldInfo fieldInfo = tableInfo.getFieldList().stream().filter(f ->
f.getField().getName().equals(this.thisProperty)).findFirst().orElse(null);
Assert.notNull(fieldInfo, "MPJMapping注解thisField不存在 %s , %s", entityType.getName(),
StringUtils.isBlank(this.thisProperty) ? "主键" : this.thisProperty);
this.thisField = fieldInfo.getField();
this.thisColumn = fieldInfo.getColumn();
}
this.thisField.setAccessible(true);
}
return this.thisField;
}
public String getJoinColumn() {
if (StringUtils.isBlank(this.joinColumn)) {
TableInfo joinTableInfo = getTableInfo(this.joinClass);
TableFieldInfo joinFieldInfo = joinTableInfo.getFieldList().stream().filter(f ->
f.getField().getName().equals(this.joinProperty)).findFirst().orElse(null);
if (joinFieldInfo == null) {
if (joinTableInfo.havePK() && this.joinProperty.equals(joinTableInfo.getKeyProperty())) {
this.joinColumn = joinTableInfo.getKeyColumn();
this.joinField = ReflectionKit.getFieldList(this.joinClass).stream().filter(i ->
i.getName().equals(joinTableInfo.getKeyProperty())).findFirst().orElse(null);
if (!this.fieldIsMap) {
if (List.class.isAssignableFrom(field.getType())) {
if (field.getGenericType() instanceof ParameterizedType) {
ParameterizedType t = (ParameterizedType) field.getGenericType();
this.joinClass = (Class<?>) t.getActualTypeArguments()[0];
}
} else {
this.joinColumn = joinFieldInfo.getColumn();
this.joinField = joinFieldInfo.getField();
this.joinClass = field.getType();
}
Assert.notNull(this.joinField, "MPJMapping注解thisField不存在 %s , %s", this.joinClass.getName(),
StringUtils.isBlank(this.joinProperty) ? "主键" : this.joinProperty);
Assert.notNull(this.joinColumn, "MPJMapping注解thisField不存在 %s , %s", this.joinClass.getName(),
StringUtils.isBlank(this.joinProperty) ? "主键" : this.joinProperty);
this.joinField.setAccessible(true);
}
return this.joinColumn;
}
public String getThisMapKey() {
if (this.thisMapKey == null) {
this.thisMapKey = getJoinColumn();
}
return this.thisMapKey;
}
public Field getJoinField() {
if (this.joinField == null) {
this.getJoinColumn();
}
return this.joinField;
}
public String getJoinMapKey() {
if (this.joinMapKey == null) {
this.joinMapKey = getJoinColumn();
}
return joinMapKey;
}
public MPJBaseMapper<?> getJoinMapper() {
@ -283,6 +312,35 @@ public class MPJTableFieldInfo {
}
}
public Object bindFieldGet(Object o) {
try {
return getBindField().get(o);
} catch (Exception e) {
throw new MPJException("无法设置关联字段,请检查关联字段数据类型是否匹配 " + this.joinClass.getName() + " , " +
this.bindField.getName() + " , " + o.getClass().getName());
}
}
public void joinFieldSetNull(Object o) {
try {
this.joinField.set(o, null);
} catch (Exception e) {
throw new MPJException("无法设置关联字段,请检查关联字段数据类型是否匹配 " + this.entityType.getName() +
" , " + this.joinField.getName() + " , " + o.getClass().getName());
}
}
@SuppressWarnings({"unchecked", "RedundantCast"})
public void removeJoinField(List<?> joinList) {
if (this.isMappingEntity() && this.isRemoveBindField()) {
if (this.isFieldIsMap()) {
((List<Map<String, Object>>) joinList).forEach(m -> m.remove(this.getJoinMapKey()));
} else {
joinList.forEach(this::joinFieldSetNull);
}
}
}
public static <T> void bind(MPJTableFieldInfo fieldInfo, T i, List<?> data) {
if (fieldInfo.isCollection()) {
fieldInfo.fieldSet(i, data);
@ -308,6 +366,4 @@ public class MPJTableFieldInfo {
}
}
}
}

View File

@ -25,27 +25,27 @@ public class MPJTableInfo {
private TableInfo tableInfo;
/**
* 表别名
* 是否包含 MPJMapping 或者 MPJMappingField
*/
private String alias;
/**
* 前缀
*/
private String aliasDOT;
private boolean hasMappingOrField;
/**
* 是否包含映射注解
*/
private boolean hasMapping;
/**
* 是否包含映射注解
*/
private boolean hasMappingField;
/**
* mapperClass
*/
private Class<?> mapperClass;
/**
* 包含映射注解的字段列表
* 包含映射实体注解的字段列表
*/
private List<MPJTableFieldInfo> fieldList;
}

View File

@ -3,9 +3,8 @@ package com.baomidou.mybatisplus.core.metadata;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.github.yulichang.annotation.MPJMapping;
import com.github.yulichang.annotation.MPJTableAlias;
import com.github.yulichang.toolkit.Constant;
import com.github.yulichang.annotation.EntityMapping;
import com.github.yulichang.annotation.FieldMapping;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
@ -19,7 +18,6 @@ import org.apache.ibatis.session.Configuration;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.stream.Collectors.toList;
@ -37,10 +35,6 @@ import static java.util.stream.Collectors.toList;
*/
public class MPJTableInfoHelper {
/**
* 用于生成别名的序号
*/
private static final AtomicInteger index = new AtomicInteger(1);
private static final Log logger = LogFactory.getLog(TableInfoHelper.class);
@ -124,7 +118,6 @@ public class MPJTableInfoHelper {
TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
if (tableInfo != null) {
mpjTableInfo.setTableInfo(tableInfo);
initTableAlias(mpjTableInfo);
initMapping(mpjTableInfo);
/* 添加缓存 */
TABLE_INFO_CACHE.put(clazz, mpjTableInfo);
@ -154,24 +147,11 @@ public class MPJTableInfoHelper {
/* 缓存 lambda */
LambdaUtils.installCache(tableInfo);
/* 初始化表别名 */
initTableAlias(mpjTableInfo);
/* 初始化映射关系 */
initMapping(mpjTableInfo);
return mpjTableInfo;
}
private static void initTableAlias(MPJTableInfo tableInfo) {
MPJTableAlias tableAlias = tableInfo.getTableInfo().getEntityType().getAnnotation(MPJTableAlias.class);
if (tableAlias != null && StringUtils.isNotBlank(tableAlias.value())) {
tableInfo.setAlias(tableAlias.value());
return;
}
tableInfo.setAlias(Constant.TABLE_ALIAS + index.getAndIncrement());
tableInfo.setAliasDOT(tableInfo.getAlias() + StringPool.DOT);
}
/**
* 自动构建 resultMap 并注入(如果条件符合的话)
*/
@ -371,7 +351,11 @@ public class MPJTableInfoHelper {
}
private static boolean isExistMapping(Class<?> clazz) {
return ReflectionKit.getFieldList(ClassUtils.getUserClass(clazz)).stream().anyMatch(field -> field.isAnnotationPresent(MPJMapping.class));
return ReflectionKit.getFieldList(ClassUtils.getUserClass(clazz)).stream().anyMatch(field -> field.isAnnotationPresent(EntityMapping.class));
}
private static boolean isExistMappingField(Class<?> clazz) {
return ReflectionKit.getFieldList(ClassUtils.getUserClass(clazz)).stream().anyMatch(field -> field.isAnnotationPresent(FieldMapping.class));
}
/**
@ -512,12 +496,22 @@ public class MPJTableInfoHelper {
// 是否存在 @MPJMapping 注解
boolean existMapping = isExistMapping(mpjTableInfo.getTableInfo().getEntityType());
mpjTableInfo.setHasMapping(existMapping);
// 是否存在 @MPJMappingField 注解
boolean existMappingField = isExistMappingField(mpjTableInfo.getTableInfo().getEntityType());
mpjTableInfo.setHasMappingField(existMappingField);
mpjTableInfo.setHasMappingOrField(existMapping || existMappingField);
/* 关系映射初始化 */
List<MPJTableFieldInfo> mpjFieldList = new ArrayList<>();
List<Field> fields = ReflectionKit.getFieldList(ClassUtils.getUserClass(mpjTableInfo.getTableInfo().getEntityType()));
for (Field field : fields) {
if (existMapping) {
MPJMapping mapping = field.getAnnotation(MPJMapping.class);
EntityMapping mapping = field.getAnnotation(EntityMapping.class);
if (mapping != null) {
mpjFieldList.add(new MPJTableFieldInfo(mpjTableInfo.getTableInfo().getEntityType(), mapping, field));
}
}
if (existMappingField) {
FieldMapping mapping = field.getAnnotation(FieldMapping.class);
if (mapping != null) {
mpjFieldList.add(new MPJTableFieldInfo(mpjTableInfo.getTableInfo().getEntityType(), mapping, field));
}
@ -526,5 +520,4 @@ public class MPJTableInfoHelper {
/* 映射字段列表 */
mpjTableInfo.setFieldList(mpjFieldList);
}
}

View File

@ -4,7 +4,7 @@ package com.github.yulichang.annotation;
import java.lang.annotation.*;
/**
* 关系映射注解
* 实体类关系映射注解
*
* @author yulichang
* @since 1.2.0
@ -12,7 +12,7 @@ import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface MPJMapping {
public @interface EntityMapping {
/**
* 关联的数据库实体类<br/>
@ -56,7 +56,7 @@ public @interface MPJMapping {
* 如果此类是以map方式查询的<br/>
* 并且查询出来的map的key不是thisField对应的数据库列名就需要设置<br/>
*/
String joinMapKsy() default "";
String joinMapKey() default "";
/**
* 映射表查询条件之 select<br/>

View File

@ -0,0 +1,89 @@
package com.github.yulichang.annotation;
import java.lang.annotation.*;
/**
* 字段关系映射注解
*
* @author yulichang
* @since 1.2.0
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface FieldMapping {
/**
* 关联的数据库实体类<br/>
* 默认获取此注解所对应的类
*/
Class<?> tag();
/**
* 当前类的关联的字段名称 (是实体类字段名称而不是数据库字段名称)<br/>
* 默认获取当前类上定义的主键 @TableId
*/
String thisField() default "";
/**
* 关联类的字段名称 (是实体类字段名称而不是数据库字段名称)<br/>
* 默认获取关联类上定义的主键 @TableId
*/
String joinField() default "";
/**
* 一对一查询时 如果查询到多条记录是否抛出异常<br/>
* true 抛出异常<br/>
* false 不抛异常获取列表第一条数据<br/>
*/
boolean isThrowExp() default true;
/**
* 字段映射对应的属性名
*/
String select();
/**
* 针对查询结果map的时候使用<br/>
* 默认为thisField对应的数据库列名<br/>
* <p>
* 如果此类是以map方式查询的<br/>
* 并且查询出来的map的key不是thisField对应的数据库列名就需要设置<br/>
*/
String thisMapKey() default "";
/**
* isMap为true时生效<br/>
* 针对查询结果map的时候使用<br/>
* 默认为joinField对应的数据库列名<br/>
* <p>
* 如果此类是以map方式查询的<br/>
* 并且查询出来的map的key不是thisField对应的数据库列名就需要设置<br/>
*/
String joinMapKey() default "";
/**
* 映射表查询条件之 first<br/>
* 等效于 Wrappers.<T>query().first(xxx);
*/
String first() default "";
/**
* 映射表查询条件之 apply<br/>
* 等效于 Wrappers.<T>query().apply(xxx);
*/
MPJMappingApply[] apply() default {};
/**
* 映射表查询条件
*/
MPJMappingCondition[] condition() default {};
/**
* 映射表查询条件之 last<br/>
* 建议不要在这使用分页语句会导致关联查的时候查询不全<br/>
* 等效于 Wrappers.<T>query().last(xxx);
*/
String last() default "";
}

View File

@ -3,12 +3,12 @@ package com.github.yulichang.annotation;
import java.lang.annotation.*;
/**
* 关联查询时的表别名
* 框架默认会随机生成 一般是 t1 t2 t3 ...
* 不要在程序中使用随机别名运行期间是不变的但是重启就不一定了
* 如需使用请配合此注解一起使用
* 关联查询时的表别名<br/>
* 框架默认会随机生成 一般是 t1 t2 t3 ...<br/>
* 不要在程序中使用随机别名运行期间是不变的但是重启就不一定了<br/>
* 如需使用请配合此注解一起使用<br/>
* <p>
* 这个注解定义的表别名或者随机生成的别名只对MPJLambdaWrapper生效
* 这个注解定义的表别名或者随机生成的别名只对MPJLambdaWrapper生效<br/>
* 对MPJQueryWrapper不生效,
*
* @author yulichang
@ -21,5 +21,5 @@ import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
public @interface MPJTableAlias {
String value() default "";
String value();
}

View File

@ -190,6 +190,40 @@ public interface MPJDeepMapper<T> extends BaseMapper<T> {
return queryMapping(selectList(queryWrapper), property);
}
/**
* 根据 Wrapper 条件查询全部记录
*
* @param queryWrapper 实体对象封装操作类可以为 null
*/
default List<Map<String, Object>> selectMapsDeep(Class<T> clazz, Wrapper<T> queryWrapper) {
return queryMapMapping(selectMaps(queryWrapper), clazz, null);
}
/**
* 根据 entity 条件查询全部记录并翻页
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param clazz 实体类class
* @param queryWrapper 实体对象封装操作类可以为 null
* @param property 需要关联的字段
*/
default <R> List<Map<String, Object>> selectMapsDeep(Class<T> clazz, Wrapper<T> queryWrapper, SFunction<T, R>... property) {
return queryMapMapping(selectMaps(queryWrapper), clazz, Arrays.asList(property));
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectMapsDeep(UserDO.class, queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param queryWrapper 实体对象封装操作类可以为 null
* @param property 需要关联的字段
*/
default <R> List<Map<String, Object>> selectMapsDeep(Class<T> clazz, Wrapper<T> queryWrapper, List<SFunction<T, R>> property) {
return queryMapMapping(selectMaps(queryWrapper), clazz, property);
}
/**
* 根据 entity 条件查询全部记录并翻页
@ -234,6 +268,54 @@ public interface MPJDeepMapper<T> extends BaseMapper<T> {
return e;
}
/**
* 根据 entity 条件查询全部记录并翻页
*
* @param page 分页查询条件可以为 RowBounds.DEFAULT
* @param queryWrapper 实体对象封装操作类可以为 null
*/
default <R, E extends IPage<Map<String, Object>>> E selectMapsPageDeep(E page, Class<T> clazz, Wrapper<T> queryWrapper) {
E e = selectMapsPage(page, queryWrapper);
queryMapMapping(e.getRecords(), clazz, null);
return e;
}
/**
* 根据 entity 条件查询全部记录并翻页
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param page 分页查询条件可以为 RowBounds.DEFAULT
* @param queryWrapper 实体对象封装操作类可以为 null
* @param property 需要关联的字段
*/
default <R, E extends IPage<Map<String, Object>>> E selectMapsPageDeep(E page, Class<T> clazz, Wrapper<T> queryWrapper,
SFunction<T, R>... property) {
E e = selectMapsPage(page, queryWrapper);
queryMapMapping(e.getRecords(), clazz, Arrays.asList(property));
return e;
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectMapsPage(page, UserDO.class, queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param page 分页查询条件可以为 RowBounds.DEFAULT
* @param queryWrapper 实体对象封装操作类可以为 null
* @param property 需要关联的字段
*/
default <R, E extends IPage<Map<String, Object>>> E selectMapsPageDeep(E page, Class<T> clazz, Wrapper<T> queryWrapper,
List<SFunction<T, R>> property) {
E e = selectMapsPage(page, queryWrapper);
queryMapMapping(e.getRecords(), clazz, property);
return e;
}
/**
* 查询映射关系<br/>
* 对结果进行二次查询<br/>
@ -247,17 +329,18 @@ public interface MPJDeepMapper<T> extends BaseMapper<T> {
return null;
}
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(t.getClass());
if (tableInfo.isHasMapping()) {
if (tableInfo.isHasMappingOrField()) {
boolean hasProperty = CollectionUtils.isNotEmpty(property);
List<String> list = hasProperty ? property.stream().map(LambdaUtils::getName).collect(
Collectors.toList()) : null;
for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) {
if (!hasProperty || list.contains(fieldInfo.getProperty())) {
Object get = fieldInfo.thisFieldGet(t);
if (get != null) {
List<?> o = (List<?>) fieldInfo.getJoinMapper().mappingWrapperConstructor(fieldInfo.isFieldIsMap(),
SqlKeyword.EQ, fieldInfo.getJoinColumn(), get, fieldInfo);
MPJTableFieldInfo.bind(fieldInfo, t, o);
Object obj = fieldInfo.thisFieldGet(t);
if (obj != null) {
List<?> joinList = (List<?>) fieldInfo.getJoinMapper().mappingWrapperConstructor(
fieldInfo.isFieldIsMap(), SqlKeyword.EQ, fieldInfo.getJoinColumn(), obj, fieldInfo);
bindData(t, fieldInfo, joinList);
fieldInfo.removeJoinField(joinList);
}
}
}
@ -265,6 +348,38 @@ public interface MPJDeepMapper<T> extends BaseMapper<T> {
return t;
}
/**
* 查询映射关系<br/>
* 对结果进行二次查询<br/>
* 可以自行查询然后在通过此方法进行二次查询<br/>
* list为null或空会查询全部映射关系<br/>
*
* @param map 第一次查询结果
*/
default <R> Map<String, Object> queryMapMapping(Map<String, Object> map, Class<T> clazz, List<SFunction<T, R>> property) {
if (CollectionUtils.isEmpty(map)) {
return map;
}
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(clazz);
if (tableInfo.isHasMappingOrField()) {
boolean hasProperty = CollectionUtils.isNotEmpty(property);
List<String> list = hasProperty ? property.stream().map(LambdaUtils::getName).collect(
Collectors.toList()) : null;
for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) {
if (!hasProperty || list.contains(fieldInfo.getProperty())) {
Object obj = map.get(fieldInfo.getThisMapKey());
if (obj != null) {
List<?> joinList = (List<?>) fieldInfo.getJoinMapper().mappingWrapperConstructor(
fieldInfo.isFieldIsMap(), SqlKeyword.EQ, fieldInfo.getJoinColumn(), obj, fieldInfo);
bindMap(map, fieldInfo, joinList);
fieldInfo.removeJoinField(joinList);
}
}
}
}
return map;
}
/**
* 查询映射关系<br/>
* 对结果进行二次查询<br/>
@ -278,7 +393,7 @@ public interface MPJDeepMapper<T> extends BaseMapper<T> {
return list;
}
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(list.get(0).getClass());
if (tableInfo.isHasMapping()) {
if (tableInfo.isHasMappingOrField()) {
boolean hasProperty = CollectionUtils.isNotEmpty(property);
List<String> listProperty = hasProperty ? property.stream().map(LambdaUtils::getName).collect(
Collectors.toList()) : null;
@ -287,12 +402,10 @@ public interface MPJDeepMapper<T> extends BaseMapper<T> {
List<Object> itemList = list.stream().map(fieldInfo::thisFieldGet).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(itemList)) {
List<?> joinList = (List<?>) fieldInfo.getJoinMapper().mappingWrapperConstructor(
fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo);
list.forEach(i -> {
List<?> data = joinList.stream().filter(j -> fieldInfo.joinFieldGet(j)
.equals(fieldInfo.thisFieldGet(i))).collect(Collectors.toList());
MPJTableFieldInfo.bind(fieldInfo, i, data);
});
fieldInfo.isMappingEntity() && fieldInfo.isFieldIsMap(), SqlKeyword.IN,
fieldInfo.getJoinColumn(), itemList, fieldInfo);
list.forEach(i -> bindData(i, fieldInfo, joinList));
fieldInfo.removeJoinField(joinList);
} else {
list.forEach(i -> fieldInfo.fieldSet(i, new ArrayList<>()));
}
@ -302,9 +415,83 @@ public interface MPJDeepMapper<T> extends BaseMapper<T> {
return list;
}
/**
* 查询映射关系<br/>
* 对结果进行二次查询<br/>
* 可以自行查询然后在通过此方法进行二次查询<br/>
* list为null或空会查询全部映射关系<br/>
*
* @param list 第一次查询结果
*/
default <R> List<Map<String, Object>> queryMapMapping(List<Map<String, Object>> list, Class<T> clazz, List<SFunction<T, R>> property) {
if (CollectionUtils.isEmpty(list)) {
return list;
}
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(clazz);
if (tableInfo.isHasMappingOrField()) {
boolean hasProperty = CollectionUtils.isNotEmpty(property);
List<String> listProperty = hasProperty ? property.stream().map(LambdaUtils::getName).collect(
Collectors.toList()) : null;
for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) {
if (!hasProperty || listProperty.contains(fieldInfo.getProperty())) {
List<Object> itemList = list.stream().map(m -> m.get(fieldInfo.getThisMapKey()))
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(itemList)) {
List<?> joinList = (List<?>) fieldInfo.getJoinMapper().mappingWrapperConstructor(
fieldInfo.isMappingEntity() && fieldInfo.isFieldIsMap(), SqlKeyword.IN,
fieldInfo.getJoinColumn(), itemList, fieldInfo);
list.forEach(i -> bindMap(i, fieldInfo, joinList));
fieldInfo.removeJoinField(joinList);
} else {
list.forEach(i -> i.put(fieldInfo.getField().getName(), new ArrayList<>()));
}
}
}
}
return list;
}
/**
* 绑定数据
*/
default void bindData(T t, MPJTableFieldInfo fieldInfo, List<?> joinList) {
if (fieldInfo.isMappingEntity()) {
List<?> list = joinList.stream().filter(j -> fieldInfo.joinFieldGet(j).equals(fieldInfo.thisFieldGet(t)))
.collect(Collectors.toList());
MPJTableFieldInfo.bind(fieldInfo, t, list);
}
if (fieldInfo.isMappingField()) {
MPJTableFieldInfo.bind(fieldInfo, t, joinList.stream().filter(j -> fieldInfo.joinFieldGet(j).equals(
fieldInfo.thisFieldGet(t))).map(fieldInfo::bindFieldGet).collect(Collectors.toList()));
}
}
/**
* 绑定数据
*/
default void bindMap(Map<String, Object> t, MPJTableFieldInfo fieldInfo, List<?> joinList) {
List<?> list = null;
if (fieldInfo.isMappingEntity()) {
if (fieldInfo.isFieldIsMap()) {
list = ((List<Map<String, Object>>) joinList).stream().filter(j ->
j.get(fieldInfo.getJoinMapKey()).equals(t.get(fieldInfo.getThisMapKey())))
.collect(Collectors.toList());
} else {
list = joinList.stream().filter(j ->
fieldInfo.joinFieldGet(j).equals(t.get(fieldInfo.getThisMapKey())))
.collect(Collectors.toList());
}
}
if (fieldInfo.isMappingField()) {
list = joinList.stream().filter(j -> fieldInfo.joinFieldGet(j).equals(
t.get(fieldInfo.getThisMapKey()))).map(fieldInfo::bindFieldGet).collect(Collectors.toList());
}
MPJTableFieldInfo.bindMap(fieldInfo, t, list);
}
/**
* 映射 wrapper 构造器
* 仅对使用 @MPJMapping 时使用
* 仅对使用映射注解时使用
*/
default Object mappingWrapperConstructor(boolean selectMap, SqlKeyword keyword,
String column, Object val, MPJTableFieldInfo fieldInfo) {

View File

@ -1,22 +1,18 @@
package com.github.yulichang.base.service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.MPJTableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.MPJTableInfo;
import com.baomidou.mybatisplus.core.metadata.MPJTableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.IService;
import com.github.yulichang.annotation.MPJMapping;
import com.github.yulichang.annotation.EntityMapping;
import com.github.yulichang.base.MPJBaseMapper;
import com.github.yulichang.toolkit.LambdaUtils;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 深度查询
@ -26,7 +22,7 @@ import java.util.stream.Collectors;
* 多级查询可能存在循环引用的问题也可能会导致全量查询
*
* @author yulichang
* @see MPJMapping
* @see EntityMapping
* @since 1.2.0
*/
@SuppressWarnings({"unused", "unchecked"})
@ -217,7 +213,8 @@ public interface MPJDeepService<T> extends IService<T> {
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default Map<String, Object> getMapDeep(Wrapper<T> queryWrapper) {
return queryMapMapping(getMap(queryWrapper), null);
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(getMap(queryWrapper), currentModelClass(),
null);
}
/**
@ -229,7 +226,8 @@ public interface MPJDeepService<T> extends IService<T> {
* @param property 需要关联的字段
*/
default <R> Map<String, Object> getMapDeep(Wrapper<T> queryWrapper, SFunction<T, R>... property) {
return queryMapMapping(getMap(queryWrapper), Arrays.asList(property));
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(getMap(queryWrapper), currentModelClass(),
Arrays.asList(property));
}
/**
@ -242,7 +240,7 @@ public interface MPJDeepService<T> extends IService<T> {
* @param property 需要关联的字段
*/
default <R> Map<String, Object> getMapDeep(Wrapper<T> queryWrapper, List<SFunction<T, R>> property) {
return queryMapMapping(getMap(queryWrapper), property);
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(getMap(queryWrapper), currentModelClass(), property);
}
/**
@ -405,7 +403,7 @@ public interface MPJDeepService<T> extends IService<T> {
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default List<Map<String, Object>> listMapsDeep(Wrapper<T> queryWrapper) {
return queryMapMapping(listMaps(queryWrapper), null);
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(listMaps(queryWrapper), currentModelClass(), null);
}
/**
@ -417,7 +415,8 @@ public interface MPJDeepService<T> extends IService<T> {
* @param property 需要关联的字段
*/
default <R> List<Map<String, Object>> listMapsDeep(Wrapper<T> queryWrapper, SFunction<T, R>... property) {
return queryMapMapping(listMaps(queryWrapper), Arrays.asList(property));
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(listMaps(queryWrapper), currentModelClass(),
Arrays.asList(property));
}
/**
@ -430,7 +429,7 @@ public interface MPJDeepService<T> extends IService<T> {
* @param property 需要关联的字段
*/
default <R> List<Map<String, Object>> listMapsDeep(Wrapper<T> queryWrapper, List<SFunction<T, R>> property) {
return queryMapMapping(listMaps(queryWrapper), property);
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(listMaps(queryWrapper), currentModelClass(), property);
}
/**
@ -439,7 +438,7 @@ public interface MPJDeepService<T> extends IService<T> {
* @see Wrappers#emptyWrapper()
*/
default List<Map<String, Object>> listMapsDeep() {
return queryMapMapping(listMaps(), null);
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(listMaps(), currentModelClass(), null);
}
/**
@ -451,7 +450,7 @@ public interface MPJDeepService<T> extends IService<T> {
* @see Wrappers#emptyWrapper()
*/
default <R> List<Map<String, Object>> listMapsDeep(SFunction<T, R>... property) {
return queryMapMapping(listMaps(), Arrays.asList(property));
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(listMaps(), currentModelClass(), Arrays.asList(property));
}
/**
@ -464,7 +463,7 @@ public interface MPJDeepService<T> extends IService<T> {
* @see Wrappers#emptyWrapper()
*/
default <R> List<Map<String, Object>> listMapsDeep(List<SFunction<T, R>> property) {
return queryMapMapping(listMaps(), property);
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(listMaps(), currentModelClass(), property);
}
/**
@ -475,7 +474,7 @@ public interface MPJDeepService<T> extends IService<T> {
*/
default <E extends IPage<Map<String, Object>>> E pageMapsDeep(E page, Wrapper<T> queryWrapper) {
E e = pageMaps(page, queryWrapper);
queryMapMapping(e.getRecords(), null);
((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(e.getRecords(), currentModelClass(), null);
return e;
}
@ -490,7 +489,7 @@ public interface MPJDeepService<T> extends IService<T> {
*/
default <R, E extends IPage<Map<String, Object>>> E pageMapsDeep(E page, Wrapper<T> queryWrapper, SFunction<T, R>... property) {
E e = pageMaps(page, queryWrapper);
queryMapMapping(e.getRecords(), Arrays.asList(property));
((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(e.getRecords(), currentModelClass(), Arrays.asList(property));
return e;
}
@ -506,7 +505,7 @@ public interface MPJDeepService<T> extends IService<T> {
*/
default <R, E extends IPage<Map<String, Object>>> E pageMapsDeep(E page, Wrapper<T> queryWrapper, List<SFunction<T, R>> property) {
E e = pageMaps(page, queryWrapper);
queryMapMapping(e.getRecords(), property);
((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(e.getRecords(), currentModelClass(), property);
return e;
}
@ -518,7 +517,7 @@ public interface MPJDeepService<T> extends IService<T> {
*/
default <E extends IPage<Map<String, Object>>> E pageMapsDeep(E page) {
E e = pageMaps(page);
queryMapMapping(e.getRecords(), null);
((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(e.getRecords(), currentModelClass(), null);
return e;
}
@ -533,7 +532,7 @@ public interface MPJDeepService<T> extends IService<T> {
*/
default <R, E extends IPage<Map<String, Object>>> E pageMapsDeep(E page, SFunction<T, R>... property) {
E e = pageMaps(page);
queryMapMapping(e.getRecords(), Arrays.asList(property));
((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(e.getRecords(), currentModelClass(), Arrays.asList(property));
return e;
}
@ -549,90 +548,7 @@ public interface MPJDeepService<T> extends IService<T> {
*/
default <R, E extends IPage<Map<String, Object>>> E pageMapsDeep(E page, List<SFunction<T, R>> property) {
E e = pageMaps(page);
queryMapMapping(e.getRecords(), property);
((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(e.getRecords(), currentModelClass(), property);
return e;
}
/**
* 查询映射关系<br/>
* 对结果进行二次查询<br/>
* 可以自行查询然后在通过此方法进行二次查询<br/>
* list为null或空会查询全部映射关系<br/>
*
* @param map 第一次查询结果
*/
default <R> Map<String, Object> queryMapMapping(Map<String, Object> map, List<SFunction<T, R>> property) {
if (CollectionUtils.isNotEmpty(map)) {
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass());
if (tableInfo.isHasMapping()) {
boolean hasProperty = CollectionUtils.isNotEmpty(property);
List<String> list = hasProperty ? property.stream().map(LambdaUtils::getName).collect(
Collectors.toList()) : null;
for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) {
if (!hasProperty || list.contains(fieldInfo.getProperty())) {
Object o = map.get(fieldInfo.getThisMapKey());
if (o != null) {
List<?> data = (List<?>) fieldInfo.getJoinMapper().mappingWrapperConstructor(
fieldInfo.isFieldIsMap(), SqlKeyword.EQ, fieldInfo.getJoinColumn(), o, fieldInfo);
MPJTableFieldInfo.bindMap(fieldInfo, map, data);
}
}
}
}
}
return map;
}
/**
* 查询映射关系<br/>
* 对结果进行二次查询<br/>
* 可以自行查询然后在通过此方法进行二次查询<br/>
* list为null或空会查询全部映射关系<br/>
*
* @param list 第一次查询结果
*/
@SuppressWarnings("unchecked")
default <R> List<Map<String, Object>> queryMapMapping(List<Map<String, Object>> list, List<SFunction<T, R>> property) {
if (CollectionUtils.isEmpty(list)) {
return list;
}
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass());
if (tableInfo.isHasMapping()) {
boolean hasProperty = CollectionUtils.isNotEmpty(property);
List<String> listProperty = hasProperty ? property.stream().map(LambdaUtils::getName).collect(
Collectors.toList()) : null;
for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) {
if (!hasProperty || listProperty.contains(fieldInfo.getProperty())) {
List<Object> itemList = list.stream().map(m -> m.get(fieldInfo.getThisMapKey()))
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(itemList)) {
if (fieldInfo.isFieldIsMap()) {
List<Map<String, Object>> joinList = (List<Map<String, Object>>) fieldInfo.getJoinMapper()
.mappingWrapperConstructor(fieldInfo.isFieldIsMap(), SqlKeyword.IN,
fieldInfo.getJoinColumn(), itemList, fieldInfo);
list.forEach(i -> {
List<Map<String, Object>> data = joinList.stream().filter(j -> j.containsKey(
fieldInfo.getJoinMapKey()) && j.get(fieldInfo.getJoinMapKey()).equals(
i.get(fieldInfo.getThisMapKey()))).collect(Collectors.toList());
MPJTableFieldInfo.bindMap(fieldInfo, i, data);
});
} else {
List<?> joinList = (List<?>) fieldInfo.getJoinMapper().mappingWrapperConstructor(
fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo);
list.forEach(i -> {
List<?> data = joinList.stream().filter(j -> {
Object o = fieldInfo.joinFieldGet(j);
return o != null && o.equals(i.get(fieldInfo.getThisMapKey()));
}).collect(Collectors.toList());
MPJTableFieldInfo.bindMap(fieldInfo, i, data);
});
}
} else {
list.forEach(i -> i.put(fieldInfo.getField().getName(), new ArrayList<>()));
}
}
}
}
return list;
}
}

View File

@ -3,21 +3,17 @@ package com.github.yulichang.injector;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.mapper.Mapper;
import com.baomidou.mybatisplus.core.metadata.MPJTableAliasHelper;
import com.baomidou.mybatisplus.core.metadata.MPJTableInfoHelper;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
import com.github.yulichang.method.*;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.core.GenericTypeResolver;
import java.util.List;
import java.util.Set;
import java.util.Objects;
/**
* SQL 注入器
@ -28,8 +24,6 @@ import java.util.Set;
@ConditionalOnMissingBean(DefaultSqlInjector.class)
public class MPJSqlInjector extends DefaultSqlInjector {
private static final Log logger = LogFactory.getLog(MPJSqlInjector.class);
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> list = super.getMethodList(mapperClass);
@ -45,23 +39,10 @@ public class MPJSqlInjector extends DefaultSqlInjector {
@Override
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
Class<?> modelClass = getSuperClassGenericType(mapperClass, Mapper.class, 0);
if (modelClass != null) {
String className = mapperClass.toString();
Set<String> mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration());
if (!mapperRegistryCache.contains(className)) {
List<AbstractMethod> methodList = this.getMethodList(mapperClass);
if (CollectionUtils.isNotEmpty(methodList)) {
TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
MPJTableInfoHelper.initTableInfo(builderAssistant, modelClass, mapperClass);
// 循环注入自定义方法
methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));
} else {
logger.debug(mapperClass.toString() + ", No effective injection method was found.");
}
mapperRegistryCache.add(className);
}
}
MPJTableAliasHelper.init(Objects.requireNonNull(getSuperClassGenericType(mapperClass, Mapper.class, 0)));
super.inspectInject(builderAssistant, mapperClass);
TableInfoHelper.getTableInfos().forEach(i ->
MPJTableInfoHelper.initTableInfo(builderAssistant, i.getEntityType(), mapperClass));
}
public static Class<?> getSuperClassGenericType(final Class<?> clazz, final Class<?> genericIfc, final int index) {

View File

@ -1,7 +1,7 @@
package com.github.yulichang.method;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.MPJTableInfoHelper;
import com.baomidou.mybatisplus.core.metadata.MPJTableAliasHelper;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
@ -40,7 +40,7 @@ public abstract class MPJAbstractMethod extends AbstractMethod {
String[] columns = selectColumns.split(StringPool.COMMA);
List<String> selectColumnList = new ArrayList<>();
for (String c : columns) {
selectColumnList.add(MPJTableInfoHelper.getTableInfo(table.getEntityType()).getAlias() + StringPool.DOT + c);
selectColumnList.add(MPJTableAliasHelper.get(table.getEntityType()).getAlias() + StringPool.DOT + c);
}
selectColumns = String.join(StringPool.COMMA, selectColumnList);
}
@ -60,7 +60,7 @@ public abstract class MPJAbstractMethod extends AbstractMethod {
protected String sqlAlias(Class<?> modelClass) {
return SqlScriptUtils.convertChoose(String.format("%s != null and %s != ''", "ew.autoAlias", "ew.autoAlias"),
MPJTableInfoHelper.getTableInfo(modelClass).getAlias(), "${ew.alias}");
MPJTableAliasHelper.get(modelClass).getAlias(), "${ew.alias}");
}
protected String sqlFrom() {

View File

@ -194,6 +194,7 @@ public class MPJLambdaQueryWrapper<T> extends AbstractLambdaWrapper<T, MPJLambda
* @param clazz 表实体
* @param as 表别名
*/
@SuppressWarnings("DuplicatedCode")
public final MPJLambdaQueryWrapper<T> selectAll(Class<?> clazz, String as) {
TableInfo info = TableInfoHelper.getTableInfo(clazz);
Assert.notNull(info, "can not find table info");

View File

@ -189,6 +189,7 @@ public class MPJQueryWrapper<T> extends AbstractWrapper<T, String, MPJQueryWrapp
/**
* 返回一个支持 lambda 函数写法的 wrapper
*/
@SuppressWarnings("deprecation")
public MPJLambdaQueryWrapper<T> lambda() {
return new MPJLambdaQueryWrapper<>(getEntity(), getEntityClass(), from, sqlSelect, paramNameSeq, paramNameValuePairs,
expression, lastSql, sqlComment, sqlFirst, selectColumns, ignoreColumns);

View File

@ -6,6 +6,7 @@ import com.github.yulichang.toolkit.Constant;
/**
* @author yulichang
*/
@SuppressWarnings("unused")
public interface MPJJoin<Children> extends MPJBaseJoin {
default Children leftJoin(String joinSql) {

View File

@ -11,8 +11,6 @@ public interface Constant {
*/
String TABLE_ALIAS = "t";
String AS = " AS ";
String ON = " ON ";
String JOIN = "JOIN";

View File

@ -84,6 +84,7 @@ public final class LambdaUtils {
*
* @param tableInfo 表信息
*/
@SuppressWarnings("unused")
public static void installCache(TableInfo tableInfo) {
COLUMN_CACHE_MAP.put(tableInfo.getEntityType().getName(), createColumnCacheMap(tableInfo));
}

View File

@ -39,6 +39,7 @@ import static java.util.stream.Collectors.toMap;
* @author hcl
* @since 2016-09-22
*/
@SuppressWarnings("unused")
public final class ReflectionKit {
private static final Log logger = LogFactory.getLog(ReflectionKit.class);
/**

View File

@ -8,6 +8,7 @@ import com.github.yulichang.wrapper.MPJLambdaWrapper;
*
* @author yulichang
*/
@SuppressWarnings("unused")
public class Wrappers {
/**

View File

@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import java.io.*;
/**
* copy mp before 3.4.3 {@link com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda}
* copy mp before 3.4.3
*/
@SuppressWarnings("unused")
public class SerializedLambda implements Serializable {

View File

@ -1,6 +1,6 @@
package com.github.yulichang.wrapper;
import com.baomidou.mybatisplus.core.metadata.MPJTableInfoHelper;
import com.baomidou.mybatisplus.core.metadata.MPJTableAliasHelper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
@ -42,7 +42,7 @@ public abstract class MPJAbstractLambdaWrapper<T, Children extends MPJAbstractLa
}
protected String columnToString(SFunction<?, ?> column, boolean hasAlias) {
return (hasAlias ? MPJTableInfoHelper.getTableInfo(LambdaUtils.getEntityClass(column)).getAliasDOT() :
return (hasAlias ? MPJTableAliasHelper.get(LambdaUtils.getEntityClass(column)).getAliasDOT() :
StringPool.EMPTY) + getCache(column).getColumn();
}

View File

@ -72,7 +72,7 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
MPJLambdaWrapper(Class<?> entityClass, AtomicInteger paramNameSeq,
Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments,
SharedString lastSql, SharedString sqlComment, SharedString sqlFirst, boolean hasAlias) {
this.entityClass =entityClass;
this.entityClass = entityClass;
this.paramNameSeq = paramNameSeq;
this.paramNameValuePairs = paramNameValuePairs;
this.expression = mergeSegments;
@ -107,9 +107,9 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
public <E> MPJLambdaWrapper<T> select(Class<E> entityClass, Predicate<TableFieldInfo> predicate) {
TableInfo info = TableInfoHelper.getTableInfo(entityClass);
Assert.notNull(info, "table can not be find");
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(entityClass);
MPJTableAliasHelper.TableAlias alias = MPJTableAliasHelper.get(entityClass);
info.getFieldList().stream().filter(predicate).collect(Collectors.toList()).forEach(i ->
selectColumns.add((hasAlias ? tableInfo.getAliasDOT() : StringPool.EMPTY) + i.getColumn()));
selectColumns.add((hasAlias ? alias.getAliasDOT() : StringPool.EMPTY) + i.getColumn()));
return typedThis;
}
@ -139,7 +139,7 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
public final MPJLambdaWrapper<T> selectAll(Class<?> clazz) {
TableInfo info = TableInfoHelper.getTableInfo(clazz);
Assert.notNull(info, "table can not be find -> %s", clazz);
String dot = hasAlias ? MPJTableInfoHelper.getTableInfo(clazz).getAliasDOT() : StringPool.EMPTY;
String dot = hasAlias ? MPJTableAliasHelper.get(clazz).getAliasDOT() : StringPool.EMPTY;
if (info.havePK()) {
selectColumns.add(dot + info.getKeyColumn());
}
@ -211,14 +211,14 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
public <R> MPJLambdaWrapper<T> join(String keyWord, boolean condition, Class<R> clazz, OnFunction function) {
if (condition) {
joinSql.add(keyWord + TableInfoHelper.getTableInfo(clazz).getTableName() +
Constants.SPACE + MPJTableInfoHelper.getTableInfo(clazz).getAlias() +
Constants.SPACE + MPJTableAliasHelper.get(clazz).getAlias() +
Constant.ON + function.apply(instance()).getExpression().getNormal().getSqlSegment());
}
return typedThis;
}
private String getThisAlias(SFunction<?, ?> function) {
return hasAlias ? MPJTableInfoHelper.getTableInfo(LambdaUtils.getEntityClass(function)).getAliasDOT() :
return hasAlias ? MPJTableAliasHelper.get(LambdaUtils.getEntityClass(function)).getAliasDOT() :
StringPool.EMPTY;
}
}

View File

@ -11,6 +11,7 @@ import java.util.function.BiPredicate;
* <p>
* {@link com.baomidou.mybatisplus.core.conditions.interfaces.Compare}
*/
@SuppressWarnings("unused")
public interface Compare<Children> extends Serializable {
/**
@ -65,6 +66,7 @@ public interface Compare<Children> extends Serializable {
/**
* ignore
*/
@SuppressWarnings("UnusedReturnValue")
default <R> Children eq(SFunction<R, ?> column, Object val) {
return eq(true, column, val);
}

View File

@ -11,12 +11,13 @@ import java.util.function.Consumer;
* <p>
* copy {@link com.baomidou.mybatisplus.core.conditions.interfaces.Func}
*/
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "unused"})
public interface Func<Children> extends Serializable {
/**
* ignore
*/
@SuppressWarnings("UnusedReturnValue")
default <R> Children isNull(SFunction<R, ?> column) {
return isNull(true, column);
}

View File

@ -8,6 +8,7 @@ import java.io.Serializable;
* 无改动 在mybatis 3.4.2 升级 3.4.3 后有改动 exists not exists
* 为了保证 mybatis plus 3.4.3之前的也能正常使用
*/
@SuppressWarnings("unused")
public interface Join<Children> extends Serializable {
/**

View File

@ -8,55 +8,120 @@ import com.github.yulichang.wrapper.interfaces.on.OnFunction;
/**
* @author yulichang
*/
@SuppressWarnings("unused")
public interface LambdaJoin<Children> extends MPJBaseJoin {
/**
* left join
*
* @param clazz 关联的实体类
* @param left 条件
* @param right 条件
*/
default <T, X> Children leftJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right) {
return leftJoin(true, clazz, left, right);
}
/**
* left join
* <p>
* leftJoin(UserDO.class, on -> on.eq(UserDO::getId,UserAddressDO::getUserId).le().gt()...)
*
* @param clazz 关联的实体类
* @param function 条件
*/
default <T> Children leftJoin(Class<T> clazz, OnFunction function) {
return leftJoin(true, clazz, function);
}
/**
* left join
*
* @param condition 是否执行
* @param clazz 关联的实体类
* @param left 条件
* @param right 条件
*/
default <T, X> Children leftJoin(boolean condition, Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right) {
return leftJoin(condition, clazz, on -> on.eq(left, right));
}
/**
* left join
* <p>
* leftJoin(UserDO.class, on -> on.eq(UserDO::getId,UserAddressDO::getUserId).le().gt()...)
*
* @param condition 是否执行
* @param clazz 关联实体类
* @param function 条件
*/
default <T> Children leftJoin(boolean condition, Class<T> clazz, OnFunction function) {
return join(Constant.LEFT_JOIN, condition, clazz, function);
}
/**
* ignore 参考 left join
*/
default <T, X> Children rightJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right) {
return rightJoin(true, clazz, left, right);
}
/**
* ignore 参考 left join
*/
default <T> Children rightJoin(Class<T> clazz, OnFunction function) {
return rightJoin(true, clazz, function);
}
/**
* ignore 参考 left join
*/
default <T, X> Children rightJoin(boolean condition, Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right) {
return rightJoin(condition, clazz, on -> on.eq(left, right));
}
/**
* ignore 参考 left join
*/
default <T> Children rightJoin(boolean condition, Class<T> clazz, OnFunction function) {
return join(Constant.RIGHT_JOIN, condition, clazz, function);
}
/**
* ignore 参考 left join
*/
default <T, X> Children innerJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right) {
return innerJoin(true, clazz, left, right);
}
/**
* ignore 参考 left join
*/
default <T> Children innerJoin(Class<T> clazz, OnFunction function) {
return innerJoin(true, clazz, function);
}
/**
* ignore 参考 left join
*/
default <T, X> Children innerJoin(boolean condition, Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right) {
return innerJoin(condition, clazz, on -> on.eq(left, right));
}
/**
* ignore 参考 left join
*/
default <T> Children innerJoin(boolean condition, Class<T> clazz, OnFunction function) {
return join(Constant.INNER_JOIN, condition, clazz, function);
}
/**
* 查询基类 可以直接调用此方法实现以上所有功能
*
* @param keyWord 连表关键字
* @param condition 是否执行
* @param clazz 连表实体类
* @param function 关联条件
*/
<T> Children join(String keyWord, boolean condition, Class<T> clazz, OnFunction function);
}