移除自定义别名

This commit is contained in:
yulichang 2021-11-17 12:14:48 +08:00
parent 2851cd8f5b
commit 3ff34db2ab
14 changed files with 2084 additions and 0 deletions

View File

@ -0,0 +1,104 @@
package com.baomidou.mybatisplus.core.metadata;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.github.yulichang.annotation.MPJMappingApply;
import com.github.yulichang.annotation.MPJMappingCondition;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 关联查询条件
*
* @author yulichang
* @since 1.2.0
*/
@Getter
public class MPJMappingWrapper {
private final boolean hasFirst;
private String first;
private final boolean hasSelect;
private String select;
private final boolean hasApply;
private List<Apply> applyList;
private final boolean hasCondition;
private List<Condition> conditionList;
private final boolean hasLast;
private String last;
private final boolean hasOrderByAsc;
private List<String> orderByAsc;
private final boolean hasOrderByDesc;
private List<String> orderByDesc;
public MPJMappingWrapper(String first, String select, MPJMappingApply[] applys,
MPJMappingCondition[] conditions, String last, String orderByAsc, String orderByDesc) {
this.hasFirst = StringUtils.isNotBlank(first);
if (this.hasFirst) {
this.first = first;
}
this.hasSelect = StringUtils.isNotBlank(select);
if (this.hasSelect) {
this.select = select;
}
this.hasApply = applys.length > 0;
if (this.hasApply) {
this.applyList = new ArrayList<>();
for (MPJMappingApply apply : applys) {
this.applyList.add(new Apply(apply.value(), apply.args()));
}
}
this.hasCondition = conditions.length > 0;
if (this.hasCondition) {
this.conditionList = new ArrayList<>();
for (MPJMappingCondition condition : conditions) {
conditionList.add(new Condition(condition.keyWord(), condition.column(), condition.value()));
}
}
this.hasLast = StringUtils.isNotBlank(last);
if (this.hasLast) {
this.last = last;
}
this.hasOrderByAsc = StringUtils.isNotBlank(orderByAsc);
if (this.hasOrderByAsc) {
this.orderByAsc = Arrays.asList(orderByAsc.split(StringPool.COMMA));
}
this.hasOrderByDesc = StringUtils.isNotBlank(orderByDesc);
if (this.hasOrderByDesc) {
this.orderByDesc = Arrays.asList(orderByDesc.split(StringPool.COMMA));
}
}
@Getter
@AllArgsConstructor
public static class Apply {
private final String sql;
private final String[] val;
}
@Getter
@AllArgsConstructor
public static class Condition {
private final SqlKeyword keyword;
private final String column;
private final String[] val;
}
}

View File

@ -0,0 +1,368 @@
package com.baomidou.mybatisplus.core.metadata;
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;
import lombok.EqualsAndHashCode;
import lombok.Getter;
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;
/**
* 字段属性
*
* @author yulichang
* @see TableFieldInfo
* @since 1.2.0
*/
@Getter
@ToString
@EqualsAndHashCode
public class MPJTableFieldInfo {
/**
* 是否是实体映射
*/
private final boolean isMappingEntity;
/**
* 是否是属性映射
*/
private final boolean isMappingField;
/**
* 字段映射是绑定的字段
*/
private Field bindField;
/**
* 是否移除绑定字段
*/
private final boolean isRemoveBindField;
/**
* 实体类
*/
private final Class<?> entityType;
/**
* 属性
*/
private Field field;
/**
* 属性名
*/
private String property;
/**
* 数据结构是否是Map或者List<Map>
*/
private boolean fieldIsMap;
/**
* 属性是否是集合
*/
private boolean isCollection;
/**
* 当前映射属性
*/
private Field thisField;
/**
* 当前类实体属性
*/
private String thisProperty;
/**
* 当前字段信息
*/
private String thisColumn;
/**
* 当前字段信息
*/
private String thisMapKey;
/**
* 映射实体类
*/
private Class<?> joinClass;
/**
* 映射属性名
*/
private String joinProperty;
/**
* 映射属性数据库列名
*/
private String joinColumn;
/**
* 映射属性字段
*/
private Field joinField;
/**
* fieldIsMap 为true时使用
* 映射查询Map 的key
* 默认为 关联字段的数据库列名
*/
private String joinMapKey;
/**
* 关联的mapper引用
*/
private MPJBaseMapper<?> joinMapper;
/**
* 关联查询条件配置
*/
private final MPJMappingWrapper wrapper;
/**
* 一对一查询结果数量不匹配是是否抛出异常
*/
private final boolean isThrowExp;
/**
* 初始化关联字段信息
*/
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();
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(), mapping.orderByAsc(), mapping.orderByDesc());
}
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());
}
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(), mappingField.orderByAsc(), mappingField.orderByDesc());
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();
}
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, "注解属性thisField不存在 %s , %s", this.joinClass.getName(),
StringUtils.isBlank(this.joinProperty) ? "主键" : this.joinProperty);
Assert.notNull(this.joinColumn, "注解属性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, "注解属性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, "注解属性thisField不存在 %s , %s", entityType.getName(),
StringUtils.isBlank(this.thisProperty) ? "主键" : this.thisProperty);
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) {
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 (Map.class.isAssignableFrom(field.getType())) {
this.fieldIsMap = true;
} else {
if (field.getGenericType() instanceof ParameterizedType) {
ParameterizedType t = (ParameterizedType) field.getGenericType();
Type type = t.getActualTypeArguments()[0];
if (type instanceof ParameterizedType) {
this.fieldIsMap = ((ParameterizedType) type).getRawType() == Map.class;
} else {
this.fieldIsMap = false;
}
} else {
this.fieldIsMap = false;
}
}
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.joinClass = field.getType();
}
}
}
public MPJBaseMapper<?> getJoinMapper() {
if (this.joinMapper == null) {
MPJTableInfo joinTableInfo = MPJTableInfoHelper.getTableInfos().stream().filter(table ->
table.getTableInfo().getEntityType() == this.joinClass).findFirst().orElse(null);
if (joinTableInfo == null) {
throw new MPJException("未注册 mapper " + this.joinClass.getName());
}
this.joinMapper = (MPJBaseMapper<?>) SpringContentUtils.getApplicationContext().getBean(joinTableInfo.getMapperClass());
}
return this.joinMapper;
}
private TableInfo getTableInfo(Class<?> clazz) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
if (tableInfo == null) {
throw new MPJException("未注册 mapper " + clazz.getName());
}
return tableInfo;
}
public void fieldSet(Object o, Object val) {
try {
this.field.set(o, val);
} catch (Exception e) {
throw new MPJException("无法设置关联字段,请检查关联字段数据类型是否匹配 " + this.entityType.getName() +
" , " + this.field.getName() + " , " + o.getClass().getName());
}
}
public Object thisFieldGet(Object o) {
try {
return getThisField().get(o);
} catch (Exception e) {
throw new MPJException("无法获取当前关联字段,请检查关联字段是否匹配 " + this.entityType.getName() + " , " +
this.thisField.getName() + " , " + o.getClass().getName());
}
}
public Object joinFieldGet(Object o) {
try {
return getJoinField().get(o);
} catch (Exception e) {
throw new MPJException("无法设置关联字段,请检查关联字段数据类型是否匹配 " + this.joinClass.getName() + " , " +
this.joinField.getName() + " , " + o.getClass().getName());
}
}
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);
} else {
if (data.size() > 1 && fieldInfo.isThrowExp()) {
throw new MPJException("Expected one result (or null) to be returned by select, but found: " +
data.size() + " , " + fieldInfo.getField().getName());
} else {
fieldInfo.fieldSet(i, data.stream().findFirst().orElse(null));
}
}
}
public static void bindMap(MPJTableFieldInfo fieldInfo, Map<String, Object> i, List<?> data) {
if (fieldInfo.isCollection()) {
i.put(fieldInfo.getField().getName(), data);
} else {
if (data.size() > 1 && fieldInfo.isThrowExp()) {
throw new MPJException("Expected one result (or null) to be returned by select, but found: " +
data.size() + " , " + fieldInfo.getField().getName());
} else {
i.put(fieldInfo.getField().getName(), data.stream().findFirst().orElse(null));
}
}
}
}

View File

@ -0,0 +1,51 @@
package com.baomidou.mybatisplus.core.metadata;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 数据库表反射信息
*
* @author yulichang
* @see TableInfo
* @since 1.2.0
*/
@Data
@Setter(AccessLevel.PACKAGE)
@Accessors(chain = true)
public class MPJTableInfo {
/**
* mybatis-plus 表信息
*/
private TableInfo tableInfo;
/**
* 是否包含 EntityMapping 或者 FieldMapping
*/
private boolean hasMappingOrField;
/**
* 是否包含映射注解
*/
private boolean hasMapping;
/**
* 是否包含映射注解
*/
private boolean hasMappingField;
/**
* mapperClass
*/
private Class<?> mapperClass;
/**
* 包含映射实体注解的字段列表
*/
private List<MPJTableFieldInfo> fieldList;
}

View File

@ -0,0 +1,24 @@
package com.baomidou.mybatisplus.core.metadata;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 实体类对应的mapper管理
*
* @author yulichang
* @since 1.2.0
*/
public class MPJTableMapperHelper {
private static final Map<Class<?>, Class<?>> CACHE = new ConcurrentHashMap<>();
public static void init(Class<?> clazz, Class<?> mapper) {
CACHE.put(clazz, mapper);
}
public static Class<?> get(Class<?> clazz) {
return CACHE.get(clazz);
}
}

View File

@ -0,0 +1,102 @@
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 EntityMapping {
/**
* 关联的数据库实体类<br/>
* 默认获取此注解所对应的类
*/
Class<?> tag() default Object.class;
/**
* 当前类的关联的字段名称 (是实体类字段名称而不是数据库字段名称)<br/>
* 默认获取当前类上定义的主键 @TableId
*/
String thisField() default "";
/**
* 关联类的字段名称 (是实体类字段名称而不是数据库字段名称)<br/>
* 默认获取关联类上定义的主键 @TableId
*/
String joinField() default "";
/**
* 一对一查询时 如果查询到多条记录是否抛出异常<br/>
* true 抛出异常<br/>
* false 不抛异常获取列表第一条数据<br/>
*/
boolean isThrowExp() default true;
/**
* 针对查询结果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 "";
/**
* 映射表查询条件之 select<br/>
* 等效于 Wrappers.<T>query().select(xxx);
*/
String select() default "";
/**
* 映射表查询条件之 first<br/>
* 等效于 Wrappers.<T>query().first(xxx);
*/
String first() default "";
/**
* 映射表查询条件之 apply<br/>
* 等效于 Wrappers.<T>query().apply(xxx);
*/
MPJMappingApply[] apply() default {};
/**
* 映射表查询条件
*/
MPJMappingCondition[] condition() default {};
/**
* 映射表查询条件之 orderBy<br/>
* 等效于 Wrappers.<T>query().orderByAsc(xxx);
*/
String orderByAsc() default "";
/**
* 映射表查询条件之 orderByDesc<br/>
* 等效于 Wrappers.<T>query().orderByDesc(xxx);
*/
String orderByDesc() default "";
/**
* 映射表查询条件之 last<br/>
* 建议不要在这使用分页语句会导致关联查的时候查询不全<br/>
* 等效于 Wrappers.<T>query().last(xxx);
*/
String last() default "";
}

View File

@ -0,0 +1,101 @@
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 {};
/**
* 映射表查询条件之 orderBy<br/>
* 等效于 Wrappers.<T>query().orderByAsc(xxx);
*/
String orderByAsc() default "";
/**
* 映射表查询条件之 orderByDesc<br/>
* 等效于 Wrappers.<T>query().orderByDesc(xxx);
*/
String orderByDesc() default "";
/**
* 映射表查询条件之 last<br/>
* 建议不要在这使用分页语句会导致关联查的时候查询不全<br/>
* 等效于 Wrappers.<T>query().last(xxx);
*/
String last() default "";
}

View File

@ -0,0 +1,21 @@
package com.github.yulichang.annotation;
/**
* 映射表条件
* 用法参考 mybatis plus wrapper .apply()方法
*
* @author yulichang
* @since 1.2.0
*/
public @interface MPJMappingApply {
/**
* sql片段
*/
String value();
/**
* .apply() 对应的可变参数
*/
String[] args() default {};
}

View File

@ -0,0 +1,34 @@
package com.github.yulichang.annotation;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
/**
* 映射表条件
*
* @author yulichang
* @since 1.2.0
*/
public @interface MPJMappingCondition {
/**
* 条件枚举
* 目前只实现了 = != > >= < <=
* 其他的暂未实现 TODO
*
* @see SqlKeyword
*/
SqlKeyword keyWord() default SqlKeyword.EQ;
/**
* 数据库列名
*/
String column();
/**
* 对应的值
* 一般是一个值
* 如果条件是 between 会取前两个
* 如果条件是 in 就会取全部
*/
String[] value();
}

View File

@ -0,0 +1,534 @@
package com.github.yulichang.base.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.*;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.toolkit.LambdaUtils;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author yulichang
* @see BaseMapper
*/
@SuppressWarnings({"unused", "unchecked"})
public interface MPJDeepMapper<T> extends BaseMapper<T> {
/**
* 根据 ID 查询 并关联全部映射
*
* @param id 主键ID
*/
default T selectByIdDeep(Serializable id) {
return queryMapping(selectById(id), null);
}
/**
* 根据 ID 查询 并关联指定映射
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param id 主键ID
* @param property 需要关联的字段
*/
default <R> T selectByIdDeep(Serializable id, SFunction<T, R>... property) {
return queryMapping(selectById(id), Arrays.asList(property));
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectByIdDeep(1, Arrays.asList(User::getId, ... ))
*
* @param id 主键ID
* @param property 需要关联的字段
*/
default <R> T selectByIdDeep(Serializable id, List<SFunction<T, R>> property) {
return queryMapping(selectById(id), property);
}
/**
* 查询根据ID 批量查询
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
default List<T> selectBatchIdsDeep(Collection<? extends Serializable> idList) {
return queryMapping(selectBatchIds(idList), null);
}
/**
* 查询根据ID 批量查询
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
* @param property 需要关联的字段
*/
default <R> List<T> selectBatchIdsDeep(Collection<? extends Serializable> idList, SFunction<T, R>... property) {
return queryMapping(selectBatchIds(idList), Arrays.asList(property));
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectBatchIdsDeep(idList, Arrays.asList(User::getId, ... ))
*
* @param idList 主键ID列表(不能为 null 以及 empty)
* @param property 需要关联的字段
*/
default <R> List<T> selectBatchIdsDeep(Collection<? extends Serializable> idList, List<SFunction<T, R>> property) {
return queryMapping(selectBatchIds(idList), property);
}
/**
* 查询根据 columnMap 条件
*
* @param columnMap 表字段 map 对象
*/
default List<T> selectByMapDeep(Map<String, Object> columnMap) {
return queryMapping(selectByMap(columnMap), null);
}
/**
* 查询根据 columnMap 条件
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param columnMap 表字段 map 对象
* @param property 需要关联的字段
*/
default <R> List<T> selectByMapDeep(Map<String, Object> columnMap, SFunction<T, R>... property) {
return queryMapping(selectByMap(columnMap), Arrays.asList(property));
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectByMapDeep(columnMap, Arrays.asList(User::getId, ... ))
*
* @param columnMap 表字段 map 对象
* @param property 需要关联的字段
*/
default <R> List<T> selectByMapDeep(Map<String, Object> columnMap, List<SFunction<T, R>> property) {
return queryMapping(selectByMap(columnMap), property);
}
/**
* 根据 entity 条件查询一条记录
*
* @param queryWrapper 实体对象封装操作类可以为 null
*/
default T selectOneDeep(Wrapper<T> queryWrapper) {
return queryMapping(selectOne(queryWrapper), null);
}
/**
* 根据 entity 条件查询一条记录
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param queryWrapper 实体对象封装操作类可以为 null
* @param property 需要关联的字段
*/
default <R> T selectOneDeep(Wrapper<T> queryWrapper, SFunction<T, R>... property) {
return queryMapping(selectOne(queryWrapper), Arrays.asList(property));
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectOneDeep(queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param queryWrapper 实体对象封装操作类可以为 null
* @param property 需要关联的字段
*/
default <R> T selectOneDeep(Wrapper<T> queryWrapper, List<SFunction<T, R>> property) {
return queryMapping(selectOne(queryWrapper), property);
}
/**
* 根据 entity 条件查询全部记录
*
* @param queryWrapper 实体对象封装操作类可以为 null
*/
default List<T> selectListDeep(Wrapper<T> queryWrapper) {
return queryMapping(selectList(queryWrapper), null);
}
/**
* 根据 entity 条件查询全部记录
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param queryWrapper 实体对象封装操作类可以为 null
* @param property 需要关联的字段
*/
default <R> List<T> selectListDeep(Wrapper<T> queryWrapper, SFunction<T, R>... property) {
return queryMapping(selectList(queryWrapper), Arrays.asList(property));
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectListDeep(queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param queryWrapper 实体对象封装操作类可以为 null
* @param property 需要关联的字段
*/
default <R> List<T> selectListDeep(Wrapper<T> queryWrapper, List<SFunction<T, R>> property) {
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 条件查询全部记录并翻页
*
* @param page 分页查询条件可以为 RowBounds.DEFAULT
* @param queryWrapper 实体对象封装操作类可以为 null
*/
default <E extends IPage<T>> E selectPageDeep(E page, Wrapper<T> queryWrapper) {
E e = selectPage(page, queryWrapper);
queryMapping(e.getRecords(), null);
return e;
}
/**
* 根据 entity 条件查询全部记录并翻页
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param page 分页查询条件可以为 RowBounds.DEFAULT
* @param queryWrapper 实体对象封装操作类可以为 null
* @param property 需要关联的字段
*/
default <R, E extends IPage<T>> E selectPageDeep(E page, Wrapper<T> queryWrapper, SFunction<T, R>... property) {
E e = selectPage(page, queryWrapper);
queryMapping(e.getRecords(), Arrays.asList(property));
return e;
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectPageDeep(page, queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param page 分页查询条件可以为 RowBounds.DEFAULT
* @param queryWrapper 实体对象封装操作类可以为 null
* @param property 需要关联的字段
*/
default <R, E extends IPage<T>> E selectPageDeep(E page, Wrapper<T> queryWrapper, List<SFunction<T, R>> property) {
E e = selectPage(page, queryWrapper);
queryMapping(e.getRecords(), property);
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/>
* 可以自行查询然后在通过此方法进行二次查询<br/>
* list为null或空会查询全部映射关系<br/>
*
* @param t 第一次查询结果
*/
default <R> T queryMapping(T t, List<SFunction<T, R>> property) {
if (t == null) {
return null;
}
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(t.getClass());
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 = 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);
}
}
}
}
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/>
* 可以自行查询然后在通过此方法进行二次查询<br/>
* list为null或空会查询全部映射关系<br/>
*
* @param list 第一次查询结果
*/
default <R> List<T> queryMapping(List<T> list, List<SFunction<T, R>> property) {
if (CollectionUtils.isEmpty(list)) {
return list;
}
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(list.get(0).getClass());
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(fieldInfo::thisFieldGet).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 -> bindData(i, fieldInfo, joinList));
fieldInfo.removeJoinField(joinList);
} else {
list.forEach(i -> fieldInfo.fieldSet(i, new ArrayList<>()));
}
}
}
}
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 构造器
* 仅对使用映射注解时使用
*/
default Object mappingWrapperConstructor(boolean selectMap, SqlKeyword keyword,
String column, Object val, MPJTableFieldInfo fieldInfo) {
MPJMappingWrapper infoWrapper = fieldInfo.getWrapper();
MappingQuery<T> wrapper = new MappingQuery<>();
if (infoWrapper.isHasCondition()) {
infoWrapper.getConditionList().forEach(c -> wrapper.addCondition(true, c.getColumn(),
c.getKeyword(), c.getVal()));
}
wrapper.eq(SqlKeyword.EQ == keyword, column, val)
.first(infoWrapper.isHasFirst(), infoWrapper.getFirst())
.orderByAsc(infoWrapper.isHasOrderByAsc(), infoWrapper.getOrderByAsc())
.orderByDesc(infoWrapper.isHasOrderByDesc(), infoWrapper.getOrderByDesc())
.last(infoWrapper.isHasLast(), infoWrapper.getLast());
if (SqlKeyword.IN == keyword) {
//由于Java发放调用机制 无法使用链式
wrapper.in(column, (List<?>) val);
}
if (infoWrapper.isHasSelect()) {
wrapper.select(infoWrapper.getSelect());
}
if (infoWrapper.isHasApply()) {
infoWrapper.getApplyList().forEach(a -> wrapper.apply(a.getSql(), (Object[]) a.getVal()));
}
if (selectMap) {
return selectMaps(wrapper);
}
return selectList(wrapper);
}
/**
* 公开 addCondition 方法
*/
class MappingQuery<T> extends QueryWrapper<T> {
@Override
public QueryWrapper<T> addCondition(boolean condition, String column, SqlKeyword sqlKeyword, Object val) {
return super.addCondition(condition, column, sqlKeyword, val);
}
}
}

View File

@ -0,0 +1,76 @@
package com.github.yulichang.base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.github.yulichang.interfaces.MPJBaseJoin;
import com.github.yulichang.toolkit.Constant;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* @author yulichang
* @see BaseMapper
*/
public interface MPJJoinMapper<T> extends BaseMapper<T> {
/**
* 根据 Wrapper 条件查询总记录数
*
* @param wrapper joinWrapper
*/
Integer selectJoinCount(@Param(Constants.WRAPPER) MPJBaseJoin wrapper);
/**
* 连表查询返回一条记录
*
* @param wrapper joinWrapper
* @param clazz resultType
*/
<DTO> DTO selectJoinOne(@Param(Constant.CLAZZ) Class<DTO> clazz,
@Param(Constants.WRAPPER) MPJBaseJoin wrapper);
/**
* 连表查询返回Map
*
* @param wrapper joinWrapper
*/
Map<String, Object> selectJoinMap(@Param(Constants.WRAPPER) MPJBaseJoin wrapper);
/**
* 连表查询返回记录集合
*
* @param wrapper joinWrapper
* @param clazz resultType
*/
<DTO> List<DTO> selectJoinList(@Param(Constant.CLAZZ) Class<DTO> clazz,
@Param(Constants.WRAPPER) MPJBaseJoin wrapper);
/**
* 连表查询返回Map集合
*
* @param wrapper joinWrapper
*/
List<Map<String, Object>> selectJoinMaps(@Param(Constants.WRAPPER) MPJBaseJoin wrapper);
/**
* 连表查询返回记录集合并分页
*
* @param wrapper joinWrapper
* @param clazz resultType
* @param <DTO> 分页返回对象
*/
<DTO, P extends IPage<?>> IPage<DTO> selectJoinPage(P page,
@Param(Constant.CLAZZ) Class<DTO> clazz,
@Param(Constants.WRAPPER) MPJBaseJoin wrapper);
/**
* 连表查询返回Map集合并分页
*
* @param wrapper joinWrapper
*/
<P extends IPage<?>> IPage<Map<String, Object>> selectJoinMapsPage(P page,
@Param(Constants.WRAPPER) MPJBaseJoin wrapper);
}

View File

@ -0,0 +1,556 @@
package com.github.yulichang.base.service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
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.EntityMapping;
import com.github.yulichang.annotation.FieldMapping;
import com.github.yulichang.base.MPJBaseMapper;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 深度查询
* <p>
* 对配置了映射注解的字段进行查询
* 目前查询深度只支持2级(只解析当前实体类的映射注解,不会对查询结果再次解析注解)
* 多级查询可能存在循环引用的问题也可能会导致全量查询
*
* @author yulichang
* @see EntityMapping
* @see FieldMapping
* @since 1.2.0
*/
@SuppressWarnings({"unused", "unchecked"})
public interface MPJDeepService<T> extends IService<T> {
Class<T> currentModelClass();
/**
* 根据 ID 深度查询
*
* @param id 主键ID列表
*/
default T getByIdDeep(Serializable id) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectByIdDeep(id);
}
/**
* 根据 ID 深度查询
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param id 主键ID列表
* @param property 需要关联的字段
*/
default <R> T getByIdDeep(Serializable id, SFunction<T, R>... property) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectByIdDeep(id, property);
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* getByIdDeep(id, Arrays.asList(User::getId, ... ))
*
* @param id 主键ID列表
* @param property 需要关联的字段
*/
default <R> T getByIdDeep(Serializable id, List<SFunction<T, R>> property) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectByIdDeep(id, property);
}
/**
* 查询根据ID 批量查询
*
* @param idList 主键ID列表
*/
default List<T> listByIdsDeep(Collection<? extends Serializable> idList) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectBatchIdsDeep(idList);
}
/**
* 查询根据ID 批量查询
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param idList 主键ID列表
* @param property 需要关联的字段
*/
default <R> List<T> listByIdsDeep(Collection<? extends Serializable> idList, SFunction<T, R>... property) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectBatchIdsDeep(idList, Arrays.asList(property));
}
/**
* 查询根据ID 批量查询
* list为null或空会查询全部映射关系
* <p>
* listByIdsDeep(idList, Arrays.asList(User::getId, ... ))
*
* @param idList 主键ID列表
* @param property 需要关联的字段
*/
default <R> List<T> listByIdsDeep(Collection<? extends Serializable> idList, List<SFunction<T, R>> property) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectBatchIdsDeep(idList, property);
}
/**
* 查询根据 columnMap 条件
*
* @param columnMap 表字段 map 对象
*/
default List<T> listByMapDeep(Map<String, Object> columnMap) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectByMapDeep(columnMap);
}
/**
* 查询根据 columnMap 条件
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param columnMap 表字段 map 对象
* @param property 需要关联的字段
*/
default <R> List<T> listByMapDeep(Map<String, Object> columnMap, SFunction<T, R>... property) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectByMapDeep(columnMap, Arrays.asList(property));
}
/**
* 查询根据 columnMap 条件
* list为null或空会查询全部映射关系
* <p>
* listByMapDeep(columnMap, Arrays.asList(User::getId, ... ))
*
* @param columnMap 表字段 map 对象
* @param property 需要关联的字段
*/
default <R> List<T> listByMapDeep(Map<String, Object> columnMap, List<SFunction<T, R>> property) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectByMapDeep(columnMap, property);
}
/**
* 根据 Wrapper查询一条记录 <br/>
* <p>结果集如果是多个会抛出异常随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default T getOneDeep(Wrapper<T> queryWrapper) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectOneDeep(queryWrapper);
}
/**
* 根据 Wrapper查询一条记录 <br/>
* <p>结果集如果是多个会抛出异常随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param property 需要关联的字段
*/
default <R> T getOneDeep(Wrapper<T> queryWrapper, SFunction<T, R>... property) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectOneDeep(queryWrapper, Arrays.asList(property));
}
/**
* 根据 Wrapper查询一条记录 <br/>
* list为null或空会查询全部映射关系<br/>
* <p>结果集如果是多个会抛出异常随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>
* <p>
* getOneDeep(queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param property 需要关联的字段
*/
default <R> T getOneDeep(Wrapper<T> queryWrapper, List<SFunction<T, R>> property) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectOneDeep(queryWrapper, property);
}
/**
* 根据 Wrapper查询一条记录
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param throwEx 有多个 result 是否抛出异常
*/
default T getOneDeep(Wrapper<T> queryWrapper, boolean throwEx) {
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapping(getOne(queryWrapper, throwEx), null);
}
/**
* 根据 Wrapper查询一条记录
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param throwEx 有多个 result 是否抛出异常
* @param property 需要关联的字段
*/
default <R> T getOneDeep(Wrapper<T> queryWrapper, boolean throwEx, SFunction<T, R>... property) {
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapping(getOne(queryWrapper, throwEx), Arrays.asList(property));
}
/**
* 根据 Wrapper查询一条记录
* list为null或空会查询全部映射关系
* <p>
* getOneDeep(queryWrapper, throwEx, Arrays.asList(User::getId, ... ))
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param throwEx 有多个 result 是否抛出异常
* @param property 需要关联的字段
*/
default <R> T getOneDeep(Wrapper<T> queryWrapper, boolean throwEx, List<SFunction<T, R>> property) {
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapping(getOne(queryWrapper, throwEx), property);
}
/**
* 根据 Wrapper查询一条记录
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default Map<String, Object> getMapDeep(Wrapper<T> queryWrapper) {
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(getMap(queryWrapper), currentModelClass(),
null);
}
/**
* 根据 Wrapper查询一条记录
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param property 需要关联的字段
*/
default <R> Map<String, Object> getMapDeep(Wrapper<T> queryWrapper, SFunction<T, R>... property) {
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(getMap(queryWrapper), currentModelClass(),
Arrays.asList(property));
}
/**
* 根据 Wrapper查询一条记录
* list为null或空会查询全部映射关系
* <p>
* getMapDeep(queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param property 需要关联的字段
*/
default <R> Map<String, Object> getMapDeep(Wrapper<T> queryWrapper, List<SFunction<T, R>> property) {
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(getMap(queryWrapper), currentModelClass(), property);
}
/**
* 查询列表
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default List<T> listDeep(Wrapper<T> queryWrapper) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectListDeep(queryWrapper);
}
/**
* 查询列表
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param property 需要关联的字段
*/
default <R> List<T> listDeep(Wrapper<T> queryWrapper, SFunction<T, R>... property) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectListDeep(queryWrapper, Arrays.asList(property));
}
/**
* 查询列表
* list为null或空会查询全部映射关系
* <p>
* listDeep(queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param property 需要关联的字段
*/
default <R> List<T> listDeep(Wrapper<T> queryWrapper, List<SFunction<T, R>> property) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectListDeep(queryWrapper, property);
}
/**
* 查询所有
*
* @see Wrappers#emptyWrapper()
*/
default List<T> listDeep() {
return ((MPJBaseMapper<T>) getBaseMapper()).selectListDeep(Wrappers.emptyWrapper());
}
/**
* 查询所有
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param property 需要关联的字段
* @see Wrappers#emptyWrapper()
*/
default <R> List<T> listDeep(SFunction<T, R>... property) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectListDeep(Wrappers.emptyWrapper(), Arrays.asList(property));
}
/**
* 查询所有
* list为null或空会查询全部映射关系
* <p>
* listDeep(Arrays.asList(User::getId, ... ))
*
* @param property 需要关联的字段
* @see Wrappers#emptyWrapper()
*/
default <R> List<T> listDeep(List<SFunction<T, R>> property) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectListDeep(Wrappers.emptyWrapper(), property);
}
/**
* 翻页查询
*
* @param page 翻页对象
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default <E extends IPage<T>> E pageDeep(E page, Wrapper<T> queryWrapper) {
E e = page(page, queryWrapper);
((MPJBaseMapper<T>) getBaseMapper()).queryMapping(e.getRecords(), null);
return e;
}
/**
* 翻页查询
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param page 翻页对象
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param property 需要关联的字段
*/
default <R, E extends IPage<T>> E pageDeep(E page, Wrapper<T> queryWrapper, SFunction<T, R>... property) {
E e = page(page, queryWrapper);
((MPJBaseMapper<T>) getBaseMapper()).queryMapping(e.getRecords(), Arrays.asList(property));
return e;
}
/**
* 翻页查询
* list为null或空会查询全部映射关系
* <p>
* pageDeep(page, queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param page 翻页对象
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param property 需要关联的字段
*/
default <R, E extends IPage<T>> E pageDeep(E page, Wrapper<T> queryWrapper, List<SFunction<T, R>> property) {
E e = page(page, queryWrapper);
((MPJBaseMapper<T>) getBaseMapper()).queryMapping(e.getRecords(), property);
return e;
}
/**
* 无条件翻页查询
*
* @param page 翻页对象
* @see Wrappers#emptyWrapper()
*/
default <E extends IPage<T>> E pageDeep(E page) {
E e = page(page);
((MPJBaseMapper<T>) getBaseMapper()).queryMapping(e.getRecords(), null);
return e;
}
/**
* 无条件翻页查询
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param page 翻页对象
* @param property 需要关联的字段
* @see Wrappers#emptyWrapper()
*/
default <R, E extends IPage<T>> E pageDeep(E page, SFunction<T, R>... property) {
E e = page(page);
((MPJBaseMapper<T>) getBaseMapper()).queryMapping(e.getRecords(), Arrays.asList(property));
return e;
}
/**
* 无条件翻页查询
* list为null或空会查询全部映射关系
* <p>
* pageDeep(page, Arrays.asList(User::getId, ... ))
*
* @param page 翻页对象
* @param property 需要关联的字段
* @see Wrappers#emptyWrapper()
*/
default <R, E extends IPage<T>> E pageDeep(E page, List<SFunction<T, R>> property) {
E e = page(page);
((MPJBaseMapper<T>) getBaseMapper()).queryMapping(e.getRecords(), property);
return e;
}
/**
* 查询列表
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default List<Map<String, Object>> listMapsDeep(Wrapper<T> queryWrapper) {
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(listMaps(queryWrapper), currentModelClass(), null);
}
/**
* 查询列表
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param property 需要关联的字段
*/
default <R> List<Map<String, Object>> listMapsDeep(Wrapper<T> queryWrapper, SFunction<T, R>... property) {
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(listMaps(queryWrapper), currentModelClass(),
Arrays.asList(property));
}
/**
* 查询列表
* list为null或空会查询全部映射关系
* <p>
* listMapsDeep(queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param property 需要关联的字段
*/
default <R> List<Map<String, Object>> listMapsDeep(Wrapper<T> queryWrapper, List<SFunction<T, R>> property) {
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(listMaps(queryWrapper), currentModelClass(), property);
}
/**
* 查询所有列表
*
* @see Wrappers#emptyWrapper()
*/
default List<Map<String, Object>> listMapsDeep() {
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(listMaps(), currentModelClass(), null);
}
/**
* 查询所有列表
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param property 需要关联的字段
* @see Wrappers#emptyWrapper()
*/
default <R> List<Map<String, Object>> listMapsDeep(SFunction<T, R>... property) {
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(listMaps(), currentModelClass(), Arrays.asList(property));
}
/**
* 查询所有列表
* list为null或空会查询全部映射关系
* <p>
* listMapsDeep(Arrays.asList(User::getId, ... ))
*
* @param property 需要关联的字段
* @see Wrappers#emptyWrapper()
*/
default <R> List<Map<String, Object>> listMapsDeep(List<SFunction<T, R>> property) {
return ((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(listMaps(), currentModelClass(), property);
}
/**
* 翻页查询
*
* @param page 翻页对象
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default <E extends IPage<Map<String, Object>>> E pageMapsDeep(E page, Wrapper<T> queryWrapper) {
E e = pageMaps(page, queryWrapper);
((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(e.getRecords(), currentModelClass(), null);
return e;
}
/**
* 翻页查询
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param page 翻页对象
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param property 需要关联的字段
*/
default <R, E extends IPage<Map<String, Object>>> E pageMapsDeep(E page, Wrapper<T> queryWrapper, SFunction<T, R>... property) {
E e = pageMaps(page, queryWrapper);
((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(e.getRecords(), currentModelClass(), Arrays.asList(property));
return e;
}
/**
* 翻页查询
* list为null或空会查询全部映射关系
* <p>
* pageMapsDeep(page, queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param page 翻页对象
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param property 需要关联的字段
*/
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);
((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(e.getRecords(), currentModelClass(), property);
return e;
}
/**
* 无条件翻页查询
*
* @param page 翻页对象
* @see Wrappers#emptyWrapper()
*/
default <E extends IPage<Map<String, Object>>> E pageMapsDeep(E page) {
E e = pageMaps(page);
((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(e.getRecords(), currentModelClass(), null);
return e;
}
/**
* 无条件翻页查询
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param page 翻页对象
* @param property 需要关联的字段
* @see Wrappers#emptyWrapper()
*/
default <R, E extends IPage<Map<String, Object>>> E pageMapsDeep(E page, SFunction<T, R>... property) {
E e = pageMaps(page);
((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(e.getRecords(), currentModelClass(), Arrays.asList(property));
return e;
}
/**
* 无条件翻页查询
* list为null或空会查询全部映射关系
* <p>
* pageMapsDeep(page, Arrays.asList(User::getId, ... ))
*
* @param page 翻页对象
* @param property 需要关联的字段
* @see Wrappers#emptyWrapper()
*/
default <R, E extends IPage<Map<String, Object>>> E pageMapsDeep(E page, List<SFunction<T, R>> property) {
E e = pageMaps(page);
((MPJBaseMapper<T>) getBaseMapper()).queryMapMapping(e.getRecords(), currentModelClass(), property);
return e;
}
}

View File

@ -0,0 +1,66 @@
package com.github.yulichang.base.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.github.yulichang.base.MPJBaseMapper;
import com.github.yulichang.interfaces.MPJBaseJoin;
import java.util.List;
import java.util.Map;
/**
* @author yulichang
* @see IService
*/
@SuppressWarnings("unused")
public interface MPJJoinService<T> extends IService<T> {
/**
* 根据 Wrapper 条件查询总记录数
*/
default Integer selectJoinCount(MPJBaseJoin wrapper) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinCount(wrapper);
}
/**
* 连接查询返回一条记录
*/
default <DTO> DTO selectJoinOne(Class<DTO> clazz, MPJBaseJoin wrapper) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinOne(clazz, wrapper);
}
/**
* 连接查询返回集合
*/
default <DTO> List<DTO> selectJoinList(Class<DTO> clazz, MPJBaseJoin wrapper) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinList(clazz, wrapper);
}
/**
* 连接查询返回集合并分页
*/
default <DTO, P extends IPage<?>> IPage<DTO> selectJoinListPage(P page, Class<DTO> clazz, MPJBaseJoin wrapper) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinPage(page, clazz, wrapper);
}
/**
* 连接查询返回Map
*/
default Map<String, Object> selectJoinMap(MPJBaseJoin wrapper) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinMap(wrapper);
}
/**
* 连接查询返回Map集合
*/
default List<Map<String, Object>> selectJoinMaps(MPJBaseJoin wrapper) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinMaps(wrapper);
}
/**
* 连接查询返回Map集合并分页
*/
default <P extends IPage<Map<String, Object>>> IPage<Map<String, Object>> selectJoinMapsPage(P page, MPJBaseJoin wrapper) {
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinMapsPage(page, wrapper);
}
}

View File

@ -0,0 +1,22 @@
package com.github.yulichang.config;
import com.baomidou.mybatisplus.core.metadata.MPJTableInfoHelper;
import com.baomidou.mybatisplus.core.metadata.MPJTableMapperHelper;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
/**
* 关系映射配置
*
* @author yulichang
* @since 1.2.0
*/
public class MappingConfig implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
TableInfoHelper.getTableInfos().forEach(i ->
MPJTableInfoHelper.initTableInfo(i.getEntityType(), MPJTableMapperHelper.get(i.getEntityType())));
}
}

View File

@ -0,0 +1,25 @@
package com.github.yulichang.toolkit;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* spring容器工具类
*
* @author yulichang
* @since 1.2.0
*/
public class SpringContentUtils implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return context;
}
}