mirror of
https://gitee.com/best_handsome/mybatis-plus-join
synced 2025-07-11 00:02:22 +08:00
一对一 一对多 关系映射注解实现
This commit is contained in:
parent
1f267b1cc2
commit
866bccff28
5
pom.xml
5
pom.xml
@ -4,7 +4,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.github.yulichang</groupId>
|
<groupId>com.github.yulichang</groupId>
|
||||||
<artifactId>mybatis-plus-join</artifactId>
|
<artifactId>mybatis-plus-join</artifactId>
|
||||||
<version>1.1.8</version>
|
<version>1.1.9-SNAPSHOT</version>
|
||||||
<name>mybatis-plus-join</name>
|
<name>mybatis-plus-join</name>
|
||||||
<description>An enhanced toolkit of Mybatis-Plus to simplify development.</description>
|
<description>An enhanced toolkit of Mybatis-Plus to simplify development.</description>
|
||||||
<url>https://github.com/yulichang/mybatis-plus-join</url>
|
<url>https://github.com/yulichang/mybatis-plus-join</url>
|
||||||
@ -32,6 +32,9 @@
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<jdkVersion>1.8</jdkVersion>
|
<jdkVersion>1.8</jdkVersion>
|
||||||
<jdkVersion.test>1.8</jdkVersion.test>
|
<jdkVersion.test>1.8</jdkVersion.test>
|
||||||
|
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
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;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联查询条件
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
* @since 1.2.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
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;
|
||||||
|
|
||||||
|
public MPJMappingWrapper(MPJMapping mapping) {
|
||||||
|
this.hasFirst = StringUtils.isNotBlank(mapping.first());
|
||||||
|
if (this.hasFirst) {
|
||||||
|
this.first = mapping.first();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hasSelect = StringUtils.isNotBlank(mapping.select());
|
||||||
|
if (this.hasSelect) {
|
||||||
|
this.select = mapping.select();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hasApply = mapping.apply().length > 0;
|
||||||
|
if (this.hasApply) {
|
||||||
|
this.applyList = new ArrayList<>();
|
||||||
|
for (MPJMappingApply apply : mapping.apply()) {
|
||||||
|
this.applyList.add(new Apply(apply.value(), apply.args()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hasCondition = mapping.condition().length > 0;
|
||||||
|
if (this.hasCondition) {
|
||||||
|
this.conditionList = new ArrayList<>();
|
||||||
|
for (MPJMappingCondition condition : mapping.condition()) {
|
||||||
|
conditionList.add(new Condition(condition.keyWord(), condition.column(), condition.value()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hasLast = StringUtils.isNotBlank(mapping.last());
|
||||||
|
if (this.hasLast) {
|
||||||
|
this.last = mapping.last();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class Apply {
|
||||||
|
private String sql;
|
||||||
|
private String[] val;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class Condition {
|
||||||
|
private SqlKeyword keyword;
|
||||||
|
private String column;
|
||||||
|
private String[] val;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,243 @@
|
|||||||
|
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.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.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段属性
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
* @see TableFieldInfo
|
||||||
|
* @since 1.2.0
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode
|
||||||
|
public class MPJTableFieldInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实体类
|
||||||
|
*/
|
||||||
|
private final Class<?> entityType;
|
||||||
|
/**
|
||||||
|
* 属性
|
||||||
|
*/
|
||||||
|
private final Field field;
|
||||||
|
/**
|
||||||
|
* 属性
|
||||||
|
*/
|
||||||
|
private final boolean fieldIsMap;
|
||||||
|
/**
|
||||||
|
* 属性是否是集合
|
||||||
|
*/
|
||||||
|
private final boolean isCollection;
|
||||||
|
/**
|
||||||
|
* 当前映射属性
|
||||||
|
*/
|
||||||
|
private Field thisField;
|
||||||
|
/**
|
||||||
|
* 当前类实体属性
|
||||||
|
*/
|
||||||
|
private final String thisProperty;
|
||||||
|
/**
|
||||||
|
* 当前字段信息
|
||||||
|
*/
|
||||||
|
private String thisColumn;
|
||||||
|
/**
|
||||||
|
* 当前字段信息
|
||||||
|
*/
|
||||||
|
private String thisMapKey;
|
||||||
|
/**
|
||||||
|
* 映射实体类
|
||||||
|
*/
|
||||||
|
private final Class<?> joinClass;
|
||||||
|
/**
|
||||||
|
* 映射属性名
|
||||||
|
*/
|
||||||
|
private final String joinProperty;
|
||||||
|
/**
|
||||||
|
* 映射属性数据库列名
|
||||||
|
*/
|
||||||
|
private String joinColumn;
|
||||||
|
/**
|
||||||
|
* 映射属性字段
|
||||||
|
*/
|
||||||
|
private Field joinField;
|
||||||
|
/**
|
||||||
|
* fieldIsMap 为true时使用
|
||||||
|
* 映射查询Map 的key
|
||||||
|
* 默认为 关联字段的数据库列名
|
||||||
|
*/
|
||||||
|
private String joinMapKey;
|
||||||
|
/**
|
||||||
|
* 关联的mapper引用
|
||||||
|
*/
|
||||||
|
private MPJBaseMapper<?> joinMapper;
|
||||||
|
/**
|
||||||
|
* 关联查询条件配置
|
||||||
|
*/
|
||||||
|
private final MPJMappingWrapper wrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化关联字段信息
|
||||||
|
*/
|
||||||
|
public MPJTableFieldInfo(Class<?> entityType, MPJMapping mapping, Field field) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
this.entityType = entityType;
|
||||||
|
this.field = field;
|
||||||
|
this.joinClass = mapping.tag();
|
||||||
|
this.isCollection = Collection.class.isAssignableFrom(field.getType());
|
||||||
|
this.thisMapKey = StringUtils.isBlank(mapping.thisMapKey()) ? null : mapping.thisMapKey();
|
||||||
|
this.joinMapKey = StringUtils.isBlank(mapping.joinMapKsy()) ? null : mapping.joinMapKsy();
|
||||||
|
this.fieldIsMap = mapping.isMap();//TODO 应该可以自动检测
|
||||||
|
this.wrapper = new MPJMappingWrapper(mapping);
|
||||||
|
if (this.isCollection && field.getType() != List.class && field.getType() != ArrayList.class) {
|
||||||
|
throw new MPJException("对多关系的数据结构目前只支持 <List> 暂不支持其他Collection实现 " + field.getType().getTypeName());
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(mapping.joinField())) {
|
||||||
|
this.joinProperty = mapping.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();
|
||||||
|
} else {
|
||||||
|
TableInfo info = getTableInfo(this.entityType);
|
||||||
|
Assert.isTrue(info.havePK(), "实体未定义主键 %s ", this.entityType.getName());
|
||||||
|
this.thisProperty = info.getKeyProperty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
} 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);
|
||||||
|
}
|
||||||
|
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() {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
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 {
|
||||||
|
|
||||||
|
private TableInfo tableInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否包含映射注解
|
||||||
|
*/
|
||||||
|
private boolean hasMapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mapperClass
|
||||||
|
*/
|
||||||
|
private Class<?> mapperClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 包含映射注解的字段列表
|
||||||
|
*/
|
||||||
|
private List<MPJTableFieldInfo> fieldList;
|
||||||
|
}
|
@ -3,6 +3,8 @@ package com.baomidou.mybatisplus.core.metadata;
|
|||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.*;
|
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||||
|
import com.github.yulichang.annotation.MPJMapping;
|
||||||
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
||||||
import org.apache.ibatis.logging.Log;
|
import org.apache.ibatis.logging.Log;
|
||||||
import org.apache.ibatis.logging.LogFactory;
|
import org.apache.ibatis.logging.LogFactory;
|
||||||
import org.apache.ibatis.mapping.ResultFlag;
|
import org.apache.ibatis.mapping.ResultFlag;
|
||||||
@ -38,7 +40,7 @@ public class MPJTableInfoHelper {
|
|||||||
/**
|
/**
|
||||||
* 储存反射类表信息
|
* 储存反射类表信息
|
||||||
*/
|
*/
|
||||||
private static final Map<Class<?>, TableInfo> TABLE_INFO_CACHE = new ConcurrentHashMap<>();
|
private static final Map<Class<?>, MPJTableInfo> TABLE_INFO_CACHE = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认表主键名称
|
* 默认表主键名称
|
||||||
@ -54,13 +56,47 @@ public class MPJTableInfoHelper {
|
|||||||
* @param clazz 反射实体类
|
* @param clazz 反射实体类
|
||||||
* @return 数据库表反射信息
|
* @return 数据库表反射信息
|
||||||
*/
|
*/
|
||||||
public static TableInfo getTableInfo(Class<?> clazz) {
|
public static MPJTableInfo getTableInfo(Class<?> clazz) {
|
||||||
if (clazz == null || ReflectionKit.isPrimitiveOrWrapper(clazz) || clazz == String.class || clazz.isInterface()) {
|
if (clazz == null || ReflectionKit.isPrimitiveOrWrapper(clazz) || clazz == String.class || clazz.isInterface()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return TABLE_INFO_CACHE.get(clazz);
|
return TABLE_INFO_CACHE.get(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 实体类反射获取表信息【初始化】
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param clazz 反射实体类
|
||||||
|
* @param mapperClass mapperClass
|
||||||
|
*/
|
||||||
|
public synchronized static void initTableInfo(MapperBuilderAssistant builderAssistant, Class<?> clazz, Class<?> mapperClass) {
|
||||||
|
MPJTableInfo targetTableInfo = TABLE_INFO_CACHE.get(clazz);
|
||||||
|
final Configuration configuration = builderAssistant.getConfiguration();
|
||||||
|
if (targetTableInfo != null) {
|
||||||
|
Configuration oldConfiguration = targetTableInfo.getTableInfo().getConfiguration();
|
||||||
|
if (!oldConfiguration.equals(configuration)) {
|
||||||
|
// 不是同一个 Configuration,进行重新初始化
|
||||||
|
initTableInfo(configuration, builderAssistant.getCurrentNamespace(), clazz, mapperClass);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initTableInfo(configuration, builderAssistant.getCurrentNamespace(), clazz, mapperClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 获取所有实体映射表信息
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return 数据库表反射信息集合
|
||||||
|
*/
|
||||||
|
public static List<MPJTableInfo> getTableInfos() {
|
||||||
|
return Collections.unmodifiableList(new ArrayList<>(TABLE_INFO_CACHE.values()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 实体类反射获取表信息【初始化】
|
* 实体类反射获取表信息【初始化】
|
||||||
@ -69,13 +105,26 @@ public class MPJTableInfoHelper {
|
|||||||
* @param clazz 反射实体类
|
* @param clazz 反射实体类
|
||||||
* @return 数据库表反射信息
|
* @return 数据库表反射信息
|
||||||
*/
|
*/
|
||||||
public synchronized static TableInfo initTableInfo(Configuration configuration, String currentNamespace, Class<?> clazz) {
|
public synchronized static MPJTableInfo initTableInfo(Configuration configuration, String currentNamespace, Class<?> clazz, Class<?> mapperClass) {
|
||||||
TableInfo info = TABLE_INFO_CACHE.get(clazz);
|
MPJTableInfo info = TABLE_INFO_CACHE.get(clazz);
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
/* 没有获取到缓存信息,则初始化 */
|
/* 没有获取到缓存信息,则初始化 */
|
||||||
TableInfo tableInfo = new TableInfo(clazz);
|
MPJTableInfo mpjTableInfo = new MPJTableInfo();
|
||||||
|
mpjTableInfo.setMapperClass(mapperClass);
|
||||||
|
TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
|
||||||
|
if (tableInfo != null) {
|
||||||
|
mpjTableInfo.setTableInfo(tableInfo);
|
||||||
|
initMapping(mpjTableInfo);
|
||||||
|
/* 添加缓存 */
|
||||||
|
TABLE_INFO_CACHE.put(clazz, mpjTableInfo);
|
||||||
|
return mpjTableInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tableInfo = new TableInfo(clazz);
|
||||||
|
mpjTableInfo.setTableInfo(tableInfo);
|
||||||
tableInfo.setCurrentNamespace(currentNamespace);
|
tableInfo.setCurrentNamespace(currentNamespace);
|
||||||
tableInfo.setConfiguration(configuration);
|
tableInfo.setConfiguration(configuration);
|
||||||
GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration);
|
GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration);
|
||||||
@ -86,17 +135,20 @@ public class MPJTableInfoHelper {
|
|||||||
List<String> excludePropertyList = excludeProperty != null && excludeProperty.length > 0 ? Arrays.asList(excludeProperty) : Collections.emptyList();
|
List<String> excludePropertyList = excludeProperty != null && excludeProperty.length > 0 ? Arrays.asList(excludeProperty) : Collections.emptyList();
|
||||||
|
|
||||||
/* 初始化字段相关 */
|
/* 初始化字段相关 */
|
||||||
initTableFields(clazz, globalConfig, tableInfo, excludePropertyList);
|
initTableFields(clazz, globalConfig, mpjTableInfo, excludePropertyList);
|
||||||
|
|
||||||
/* 自动构建 resultMap */
|
/* 自动构建 resultMap */
|
||||||
initResultMapIfNeed(tableInfo);
|
initResultMapIfNeed(tableInfo);
|
||||||
|
|
||||||
/* 添加缓存 */
|
/* 添加缓存 */
|
||||||
TABLE_INFO_CACHE.put(clazz, tableInfo);
|
TABLE_INFO_CACHE.put(clazz, mpjTableInfo);
|
||||||
|
|
||||||
/* 缓存 lambda */
|
/* 缓存 lambda */
|
||||||
LambdaUtils.installCache(tableInfo);
|
LambdaUtils.installCache(tableInfo);
|
||||||
return tableInfo;
|
|
||||||
|
/* 初始化映射关系 */
|
||||||
|
initMapping(mpjTableInfo);
|
||||||
|
return mpjTableInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -179,10 +231,6 @@ public class MPJTableInfoHelper {
|
|||||||
|
|
||||||
tableInfo.setTableName(targetTableName);
|
tableInfo.setTableName(targetTableName);
|
||||||
|
|
||||||
/* 开启了自定义 KEY 生成器 */
|
|
||||||
// if (CollectionUtils.isNotEmpty(dbConfig.getKeyGenerators())) {
|
|
||||||
// tableInfo.setKeySequence(clazz.getAnnotation(KeySequence.class));
|
|
||||||
// }
|
|
||||||
return excludeProperty;
|
return excludeProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,12 +264,12 @@ public class MPJTableInfoHelper {
|
|||||||
*
|
*
|
||||||
* @param clazz 实体类
|
* @param clazz 实体类
|
||||||
* @param globalConfig 全局配置
|
* @param globalConfig 全局配置
|
||||||
* @param tableInfo 数据库表反射信息
|
* @param mpjTableInfo 数据库表反射信息
|
||||||
*/
|
*/
|
||||||
private static void initTableFields(Class<?> clazz, GlobalConfig globalConfig, TableInfo tableInfo, List<String> excludeProperty) {
|
private static void initTableFields(Class<?> clazz, GlobalConfig globalConfig, MPJTableInfo mpjTableInfo, List<String> excludeProperty) {
|
||||||
/* 数据库全局配置 */
|
/* 数据库全局配置 */
|
||||||
GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
|
GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
|
||||||
ReflectorFactory reflectorFactory = tableInfo.getConfiguration().getReflectorFactory();
|
ReflectorFactory reflectorFactory = mpjTableInfo.getTableInfo().getConfiguration().getReflectorFactory();
|
||||||
Reflector reflector = reflectorFactory.findForClass(clazz);
|
Reflector reflector = reflectorFactory.findForClass(clazz);
|
||||||
List<Field> list = getAllFields(clazz);
|
List<Field> list = getAllFields(clazz);
|
||||||
// 标记是否读取到主键
|
// 标记是否读取到主键
|
||||||
@ -244,31 +292,33 @@ public class MPJTableInfoHelper {
|
|||||||
if (isReadPK) {
|
if (isReadPK) {
|
||||||
throw ExceptionUtils.mpe("@TableId can't more than one in Class: \"%s\".", clazz.getName());
|
throw ExceptionUtils.mpe("@TableId can't more than one in Class: \"%s\".", clazz.getName());
|
||||||
} else {
|
} else {
|
||||||
initTableIdWithAnnotation(dbConfig, tableInfo, field, tableId, reflector);
|
initTableIdWithAnnotation(dbConfig, mpjTableInfo.getTableInfo(), field, tableId, reflector);
|
||||||
isReadPK = true;
|
isReadPK = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!isReadPK) {
|
} else if (!isReadPK) {
|
||||||
isReadPK = initTableIdWithoutAnnotation(dbConfig, tableInfo, field, reflector);
|
isReadPK = initTableIdWithoutAnnotation(dbConfig, mpjTableInfo.getTableInfo(), field, reflector);
|
||||||
if (isReadPK) {
|
if (isReadPK) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final TableField tableField = field.getAnnotation(TableField.class);
|
final TableField tableField = field.getAnnotation(TableField.class);
|
||||||
|
|
||||||
/* 有 @TableField 注解的字段初始化 */
|
/* 有 @TableField 注解的字段初始化 */
|
||||||
if (tableField != null) {
|
if (tableField != null) {
|
||||||
fieldList.add(new TableFieldInfo(dbConfig, tableInfo, field, tableField, reflector, existTableLogic));
|
fieldList.add(new TableFieldInfo(dbConfig, mpjTableInfo.getTableInfo(), field, tableField, reflector, existTableLogic));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 无 @TableField 注解的字段初始化 */
|
/* 无 @TableField 注解的字段初始化 */
|
||||||
fieldList.add(new TableFieldInfo(dbConfig, tableInfo, field, reflector, existTableLogic));
|
fieldList.add(new TableFieldInfo(dbConfig, mpjTableInfo.getTableInfo(), field, reflector, existTableLogic));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 字段列表 */
|
/* 字段列表 */
|
||||||
tableInfo.setFieldList(fieldList);
|
mpjTableInfo.getTableInfo().setFieldList(fieldList);
|
||||||
|
|
||||||
|
|
||||||
/* 未发现主键注解,提示警告信息 */
|
/* 未发现主键注解,提示警告信息 */
|
||||||
if (!isReadPK) {
|
if (!isReadPK) {
|
||||||
@ -300,6 +350,10 @@ public class MPJTableInfoHelper {
|
|||||||
return list.stream().anyMatch(field -> field.isAnnotationPresent(TableLogic.class));
|
return list.stream().anyMatch(field -> field.isAnnotationPresent(TableLogic.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isExistMapping(Class<?> clazz) {
|
||||||
|
return ReflectionKit.getFieldList(ClassUtils.getUserClass(clazz)).stream().anyMatch(field -> field.isAnnotationPresent(MPJMapping.class));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 主键属性初始化
|
* 主键属性初始化
|
||||||
@ -430,4 +484,27 @@ public class MPJTableInfoHelper {
|
|||||||
return (tableField == null || tableField.exist());
|
return (tableField == null || tableField.exist());
|
||||||
}).collect(toList());
|
}).collect(toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化映射相关
|
||||||
|
*/
|
||||||
|
public static void initMapping(MPJTableInfo mpjTableInfo) {
|
||||||
|
// 是否存在 @MPJMapping 注解
|
||||||
|
boolean existMapping = isExistMapping(mpjTableInfo.getTableInfo().getEntityType());
|
||||||
|
mpjTableInfo.setHasMapping(existMapping);
|
||||||
|
/* 关系映射初始化 */
|
||||||
|
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);
|
||||||
|
if (mapping != null) {
|
||||||
|
mpjFieldList.add(new MPJTableFieldInfo(mpjTableInfo.getTableInfo().getEntityType(), mapping, field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 映射字段列表 */
|
||||||
|
mpjTableInfo.setFieldList(mpjFieldList);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
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 MPJMapping {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联的数据库实体类
|
||||||
|
*/
|
||||||
|
Class<?> tag();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前类的属性数据结构 是否是Map 或 List<Map>
|
||||||
|
* 如果是 true 关联查询会调用 getMap() / listMaps() 等Map相关方法进行匹配
|
||||||
|
* 如果是 false 关联查询会调用 getOne() / getById() / list() 等实体类相关方法进行匹配
|
||||||
|
*/
|
||||||
|
boolean isMap() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前类的关联的字段名称 (是实体类字段名称而不是数据库字段名称)
|
||||||
|
* 默认获取当前类上定义的主键 @TableId
|
||||||
|
*/
|
||||||
|
String thisField() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联类的字段名称 (是实体类字段名称而不是数据库字段名称)
|
||||||
|
* 默认获取关联类上定义的主键 @TableId
|
||||||
|
*/
|
||||||
|
String joinField() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 针对查询结果map的时候使用
|
||||||
|
* 默认为thisField对应的数据库列名
|
||||||
|
* <p>
|
||||||
|
* 如果此类是以map方式查询的
|
||||||
|
* 并且查询出来的map的key不是thisField对应的数据库列名就需要设置
|
||||||
|
*/
|
||||||
|
String thisMapKey() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isMap为true时生效
|
||||||
|
* 针对查询结果map的时候使用
|
||||||
|
* 默认为joinField对应的数据库列名
|
||||||
|
* <p>
|
||||||
|
* 如果此类是以map方式查询的
|
||||||
|
* 并且查询出来的map的key不是thisField对应的数据库列名就需要设置
|
||||||
|
*/
|
||||||
|
String joinMapKsy() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射表查询条件之 select
|
||||||
|
* 等效于 Wrappers.<T>query().select(xxx);
|
||||||
|
*/
|
||||||
|
String select() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射表查询条件之 first
|
||||||
|
* 等效于 Wrappers.<T>query().first(xxx);
|
||||||
|
*/
|
||||||
|
String first() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射表查询条件之 apply
|
||||||
|
* 等效于 Wrappers.<T>query().apply(xxx);
|
||||||
|
*/
|
||||||
|
MPJMappingApply[] apply() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射表查询条件
|
||||||
|
*/
|
||||||
|
MPJMappingCondition[] condition() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射表查询条件之 last
|
||||||
|
* 等效于 Wrappers.<T>query().last(xxx);
|
||||||
|
*/
|
||||||
|
String last() default "";
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
307
src/main/java/com/github/yulichang/base/MPJBaseDeepService.java
Normal file
307
src/main/java/com/github/yulichang/base/MPJBaseDeepService.java
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
package com.github.yulichang.base;
|
||||||
|
|
||||||
|
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.extension.service.IService;
|
||||||
|
import com.github.yulichang.annotation.MPJMapping;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 深度查询
|
||||||
|
* <p>
|
||||||
|
* 对配置了@MPJMapping注解的字段进行查询
|
||||||
|
* 目前查询深度只支持2级(只解析当前实体类的MPJMapping注解,不会对查询结果再次解析注解)
|
||||||
|
* 多级查询可能存在循环引用的问题,也可能会导致全量查询
|
||||||
|
*
|
||||||
|
* @author yulichang
|
||||||
|
* @see MPJMapping
|
||||||
|
* @since 1.2.0
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public interface MPJBaseDeepService<T> extends IService<T> {
|
||||||
|
|
||||||
|
Class<T> currentModelClass();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 ID 深度查询
|
||||||
|
*
|
||||||
|
* @param id 主键ID列表
|
||||||
|
*/
|
||||||
|
default <R> T getByIdDeep(Serializable id) {
|
||||||
|
return queryMapping(getById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询(根据ID 批量查询)
|
||||||
|
*
|
||||||
|
* @param idList 主键ID列表
|
||||||
|
*/
|
||||||
|
default List<T> listByIdsDeep(Collection<? extends Serializable> idList) {
|
||||||
|
return queryMapping(listByIds(idList));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询(根据 columnMap 条件)
|
||||||
|
*
|
||||||
|
* @param columnMap 表字段 map 对象
|
||||||
|
*/
|
||||||
|
default List<T> listByMapDeep(Map<String, Object> columnMap) {
|
||||||
|
return queryMapping(listByMap(columnMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 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 queryMapping(getOne(queryWrapper));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 Wrapper,查询一条记录
|
||||||
|
*
|
||||||
|
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
|
||||||
|
* @param throwEx 有多个 result 是否抛出异常
|
||||||
|
*/
|
||||||
|
default T getOneDeep(Wrapper<T> queryWrapper, boolean throwEx) {
|
||||||
|
return queryMapping(getOne(queryWrapper, throwEx));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 Wrapper,查询一条记录
|
||||||
|
*
|
||||||
|
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
|
||||||
|
*/
|
||||||
|
default Map<String, Object> getMapDeep(Wrapper<T> queryWrapper) {
|
||||||
|
Map<String, Object> map = getMap(queryWrapper);
|
||||||
|
if (CollectionUtils.isNotEmpty(map)) {
|
||||||
|
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass());
|
||||||
|
if (tableInfo.isHasMapping()) {
|
||||||
|
for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) {
|
||||||
|
Object o = map.get(fieldInfo.getThisMapKey());
|
||||||
|
if (o != null) {
|
||||||
|
map.put(fieldInfo.getField().getName(), fieldInfo.getJoinMapper()
|
||||||
|
.mappingWrapperConstructor(fieldInfo.isCollection(), fieldInfo.isFieldIsMap(), SqlKeyword.EQ,
|
||||||
|
fieldInfo.getJoinColumn(), o, fieldInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*
|
||||||
|
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
|
||||||
|
*/
|
||||||
|
default List<T> listDeep(Wrapper<T> queryWrapper) {
|
||||||
|
return queryMapping(list(queryWrapper));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询所有
|
||||||
|
*
|
||||||
|
* @see Wrappers#emptyWrapper()
|
||||||
|
*/
|
||||||
|
default List<T> listDeep() {
|
||||||
|
return queryMapping(list());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 翻页查询
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
if (CollectionUtils.isNotEmpty(e.getRecords())) {
|
||||||
|
queryMapping(e.getRecords());
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 无条件翻页查询
|
||||||
|
*
|
||||||
|
* @param page 翻页对象
|
||||||
|
* @see Wrappers#emptyWrapper()
|
||||||
|
*/
|
||||||
|
default <E extends IPage<T>> E pageDeep(E page) {
|
||||||
|
E e = page(page);
|
||||||
|
if (CollectionUtils.isNotEmpty(e.getRecords())) {
|
||||||
|
queryMapping(e.getRecords());
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*
|
||||||
|
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
|
||||||
|
*/
|
||||||
|
default List<Map<String, Object>> listMapsDeep(Wrapper<T> queryWrapper) {
|
||||||
|
return queryMapMapping(listMaps(queryWrapper));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询所有列表
|
||||||
|
*
|
||||||
|
* @see Wrappers#emptyWrapper()
|
||||||
|
*/
|
||||||
|
default List<Map<String, Object>> listMapsDeep() {
|
||||||
|
return queryMapMapping(listMaps());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 翻页查询
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
if (CollectionUtils.isNotEmpty(e.getRecords())) {
|
||||||
|
queryMapMapping(e.getRecords());
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 无条件翻页查询
|
||||||
|
*
|
||||||
|
* @param page 翻页对象
|
||||||
|
* @see Wrappers#emptyWrapper()
|
||||||
|
*/
|
||||||
|
default <E extends IPage<Map<String, Object>>> E pageMapsDeep(E page) {
|
||||||
|
E e = pageMaps(page);
|
||||||
|
if (CollectionUtils.isNotEmpty(e.getRecords())) {
|
||||||
|
queryMapMapping(e.getRecords());
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询映射关系
|
||||||
|
* 对结果进行二次查询
|
||||||
|
* 可以自行查询然后在通过此方法进行二次查询
|
||||||
|
*
|
||||||
|
* @param t 第一次查询结果
|
||||||
|
*/
|
||||||
|
default T queryMapping(T t) {
|
||||||
|
if (t == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass());
|
||||||
|
if (tableInfo.isHasMapping()) {
|
||||||
|
for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) {
|
||||||
|
Object get = fieldInfo.thisFieldGet(t);
|
||||||
|
if (get != null) {
|
||||||
|
fieldInfo.fieldSet(t, fieldInfo.getJoinMapper().mappingWrapperConstructor(fieldInfo.isCollection(),
|
||||||
|
fieldInfo.isFieldIsMap(), SqlKeyword.EQ, fieldInfo.getJoinColumn(),
|
||||||
|
get, fieldInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询映射关系
|
||||||
|
* 对结果进行二次查询
|
||||||
|
* 可以自行查询然后在通过此方法进行二次查询
|
||||||
|
*
|
||||||
|
* @param list 第一次查询结果
|
||||||
|
*/
|
||||||
|
default List<T> queryMapping(List<T> list) {
|
||||||
|
if (CollectionUtils.isEmpty(list)) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass());
|
||||||
|
if (tableInfo.isHasMapping()) {
|
||||||
|
for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) {
|
||||||
|
List<Object> itemList = list.stream().map(fieldInfo::thisFieldGet).collect(Collectors.toList());
|
||||||
|
if (CollectionUtils.isNotEmpty(itemList)) {
|
||||||
|
List<?> joinList = (List<?>) fieldInfo.getJoinMapper().mappingWrapperConstructor(true,
|
||||||
|
fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo);
|
||||||
|
list.forEach(i -> {
|
||||||
|
Stream<?> stream = joinList.stream().filter(j ->
|
||||||
|
fieldInfo.joinFieldGet(j).equals(fieldInfo.thisFieldGet(i)));
|
||||||
|
fieldInfo.fieldSet(i, fieldInfo.isCollection() ? stream.collect(Collectors.toList()) :
|
||||||
|
stream.findFirst().orElse(null));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
list.forEach(i -> fieldInfo.fieldSet(i, new ArrayList<>()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询映射关系
|
||||||
|
* 对结果进行二次查询
|
||||||
|
* 可以自行查询然后在通过此方法进行二次查询
|
||||||
|
*
|
||||||
|
* @param list 第一次查询结果
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
default List<Map<String, Object>> queryMapMapping(List<Map<String, Object>> list) {
|
||||||
|
if (CollectionUtils.isEmpty(list)) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass());
|
||||||
|
if (tableInfo.isHasMapping()) {
|
||||||
|
for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) {
|
||||||
|
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(true,
|
||||||
|
fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo);
|
||||||
|
list.forEach(i -> {
|
||||||
|
Stream<Map<String, Object>> stream = joinList.stream().filter(j -> j.containsKey(fieldInfo.getJoinMapKey())
|
||||||
|
&& j.get(fieldInfo.getJoinMapKey()).equals(i.get(fieldInfo.getThisMapKey())));
|
||||||
|
i.put(fieldInfo.getField().getName(), fieldInfo.isCollection() ? stream.collect(Collectors.toList()) :
|
||||||
|
stream.findFirst().orElse(null));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
List<?> joinList = (List<?>) fieldInfo.getJoinMapper().mappingWrapperConstructor(true,
|
||||||
|
fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo);
|
||||||
|
list.forEach(i -> {
|
||||||
|
Stream<?> stream = joinList.stream().filter(j -> {
|
||||||
|
Object o = fieldInfo.joinFieldGet(j);
|
||||||
|
return o != null && o.equals(i.get(fieldInfo.getThisMapKey()));
|
||||||
|
});
|
||||||
|
i.put(fieldInfo.getField().getName(), fieldInfo.isCollection() ? stream.collect(Collectors.toList()) :
|
||||||
|
stream.findFirst().orElse(null));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list.forEach(i -> i.put(fieldInfo.getField().getName(), new ArrayList<>()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package com.github.yulichang.base;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yulichang
|
||||||
|
* @see IService
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public interface MPJBaseJoinService<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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,11 @@
|
|||||||
package com.github.yulichang.base;
|
package com.github.yulichang.base;
|
||||||
|
|
||||||
|
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.mapper.BaseMapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.MPJMappingWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.MPJTableFieldInfo;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||||
import com.github.yulichang.toolkit.Constant;
|
import com.github.yulichang.toolkit.Constant;
|
||||||
@ -73,4 +77,47 @@ public interface MPJBaseMapper<T> extends BaseMapper<T> {
|
|||||||
*/
|
*/
|
||||||
<P extends IPage<?>> IPage<Map<String, Object>> selectJoinMapsPage(P page,
|
<P extends IPage<?>> IPage<Map<String, Object>> selectJoinMapsPage(P page,
|
||||||
@Param(Constants.WRAPPER) MPJBaseJoin wrapper);
|
@Param(Constants.WRAPPER) MPJBaseJoin wrapper);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射 wrapper 构造器
|
||||||
|
* 仅对使用 @MPJMapping 时使用
|
||||||
|
*/
|
||||||
|
default Object mappingWrapperConstructor(boolean isCollection, 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())
|
||||||
|
.last(infoWrapper.isHasLast(), infoWrapper.getLast());
|
||||||
|
if (SqlKeyword.IN == keyword) {
|
||||||
|
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 isCollection ? selectMaps(wrapper) : selectMaps(wrapper).stream().findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
return isCollection ? selectList(wrapper) : selectOne(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,50 +1,12 @@
|
|||||||
package com.github.yulichang.base;
|
package com.github.yulichang.base;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 基础service
|
||||||
|
* 目前包含两个模块 连表查询 和 关系映射
|
||||||
|
*
|
||||||
* @author yulichang
|
* @author yulichang
|
||||||
* @see IService
|
* @see MPJBaseJoinService
|
||||||
|
* @see MPJBaseDeepService
|
||||||
*/
|
*/
|
||||||
public interface MPJBaseService<T> extends IService<T> {
|
public interface MPJBaseService<T> extends MPJBaseJoinService<T>, MPJBaseDeepService<T> {
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据 Wrapper 条件,查询总记录数
|
|
||||||
*/
|
|
||||||
Integer selectJoinCount(MPJBaseJoin wrapper);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 连接查询返回一条记录
|
|
||||||
*/
|
|
||||||
<DTO> DTO selectJoinOne(Class<DTO> clazz, MPJBaseJoin wrapper);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 连接查询返回集合
|
|
||||||
*/
|
|
||||||
<DTO> List<DTO> selectJoinList(Class<DTO> clazz, MPJBaseJoin wrapper);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 连接查询返回集合并分页
|
|
||||||
*/
|
|
||||||
<DTO, P extends IPage<?>> IPage<DTO> selectJoinListPage(P page, Class<DTO> clazz, MPJBaseJoin wrapper);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 连接查询返回Map
|
|
||||||
*/
|
|
||||||
Map<String, Object> selectJoinMap(MPJBaseJoin wrapper);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 连接查询返回Map集合
|
|
||||||
*/
|
|
||||||
List<Map<String, Object>> selectJoinMaps(MPJBaseJoin wrapper);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 连接查询返回Map集合并分页
|
|
||||||
*/
|
|
||||||
<P extends IPage<Map<String, Object>>> IPage<Map<String, Object>> selectJoinMapsPage(P page, MPJBaseJoin wrapper);
|
|
||||||
}
|
}
|
||||||
|
@ -1,76 +1,16 @@
|
|||||||
package com.github.yulichang.base;
|
package com.github.yulichang.base;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
|
||||||
import com.github.yulichang.toolkit.ReflectionKit;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yulichang
|
* @author yulichang
|
||||||
* @see ServiceImpl
|
* @see ServiceImpl
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unused")
|
||||||
public class MPJBaseServiceImpl<M extends MPJBaseMapper<T>, T> extends ServiceImpl<M, T> implements MPJBaseService<T> {
|
public class MPJBaseServiceImpl<M extends MPJBaseMapper<T>, T> extends ServiceImpl<M, T> implements MPJBaseService<T> {
|
||||||
|
|
||||||
/**
|
|
||||||
* mybatis plus 3.4.3 bug
|
|
||||||
* <p>
|
|
||||||
* https://gitee.com/baomidou/mybatis-plus/issues/I3SE8R
|
|
||||||
* <p>
|
|
||||||
* https://gitee.com/baomidou/mybatis-plus/commit/7210b461b23211e6b95ca6de2d846aa392bdc28c
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<T> currentMapperClass() {
|
public Class<T> currentModelClass() {
|
||||||
return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), ServiceImpl.class, 0);
|
return super.currentModelClass();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mybatis plus 3.4.3 bug
|
|
||||||
* <p>
|
|
||||||
* https://gitee.com/baomidou/mybatis-plus/issues/I3SE8R
|
|
||||||
* <p>
|
|
||||||
* https://gitee.com/baomidou/mybatis-plus/commit/7210b461b23211e6b95ca6de2d846aa392bdc28c
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Class<T> currentModelClass() {
|
|
||||||
return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), ServiceImpl.class, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer selectJoinCount(MPJBaseJoin wrapper) {
|
|
||||||
return baseMapper.selectJoinCount(wrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <DTO> DTO selectJoinOne(Class<DTO> clazz, MPJBaseJoin wrapper) {
|
|
||||||
return baseMapper.selectJoinOne(clazz, wrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <DTO> List<DTO> selectJoinList(Class<DTO> clazz, MPJBaseJoin wrapper) {
|
|
||||||
return baseMapper.selectJoinList(clazz, wrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <DTO, P extends IPage<?>> IPage<DTO> selectJoinListPage(P page, Class<DTO> clazz, MPJBaseJoin wrapper) {
|
|
||||||
return baseMapper.selectJoinPage(page, clazz, wrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> selectJoinMap(MPJBaseJoin wrapper) {
|
|
||||||
return baseMapper.selectJoinMap(wrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Map<String, Object>> selectJoinMaps(MPJBaseJoin wrapper) {
|
|
||||||
return baseMapper.selectJoinMaps(wrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <P extends IPage<Map<String, Object>>> IPage<Map<String, Object>> selectJoinMapsPage(P page, MPJBaseJoin wrapper) {
|
|
||||||
return baseMapper.selectJoinMapsPage(page, wrapper);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,20 +2,12 @@ package com.github.yulichang.injector;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
|
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
|
||||||
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
|
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
|
||||||
import com.baomidou.mybatisplus.core.mapper.Mapper;
|
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.CollectionUtils;
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
|
|
||||||
import com.github.yulichang.method.*;
|
import com.github.yulichang.method.*;
|
||||||
import com.github.yulichang.toolkit.ReflectionKit;
|
|
||||||
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
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.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SQL 注入器
|
* SQL 注入器
|
||||||
@ -25,7 +17,6 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
@ConditionalOnMissingBean(DefaultSqlInjector.class)
|
@ConditionalOnMissingBean(DefaultSqlInjector.class)
|
||||||
public class MPJSqlInjector extends DefaultSqlInjector {
|
public class MPJSqlInjector extends DefaultSqlInjector {
|
||||||
private static final Log logger = LogFactory.getLog(MPJSqlInjector.class);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
|
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
|
||||||
@ -40,30 +31,9 @@ public class MPJSqlInjector extends DefaultSqlInjector {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* mybatis plus 3.4.3 bug
|
|
||||||
* <p>
|
|
||||||
* https://gitee.com/baomidou/mybatis-plus/issues/I3SE8R
|
|
||||||
* <p>
|
|
||||||
* https://gitee.com/baomidou/mybatis-plus/commit/7210b461b23211e6b95ca6de2d846aa392bdc28c
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
|
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
|
||||||
Class<?> modelClass = ReflectionKit.getSuperClassGenericType(mapperClass, Mapper.class, 0);
|
super.inspectInject(builderAssistant, mapperClass);
|
||||||
if (modelClass != null) {
|
MPJTableInfoHelper.initTableInfo(builderAssistant, extractModelClass(mapperClass), mapperClass);
|
||||||
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);
|
|
||||||
// 循环注入自定义方法
|
|
||||||
methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));
|
|
||||||
} else {
|
|
||||||
logger.debug(mapperClass + ", No effective injection method was found.");
|
|
||||||
}
|
|
||||||
mapperRegistryCache.add(className);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.github.yulichang.interceptor;
|
package com.github.yulichang.interceptor;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.MPJTableInfo;
|
||||||
import com.baomidou.mybatisplus.core.metadata.MPJTableInfoHelper;
|
import com.baomidou.mybatisplus.core.metadata.MPJTableInfoHelper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||||
@ -116,13 +117,13 @@ public class MPJInterceptor implements Interceptor {
|
|||||||
if (tableInfo != null && tableInfo.isAutoInitResultMap() && tableInfo.getEntityType() == resultType) {
|
if (tableInfo != null && tableInfo.isAutoInitResultMap() && tableInfo.getEntityType() == resultType) {
|
||||||
return ms.getConfiguration().getResultMap(tableInfo.getResultMap());
|
return ms.getConfiguration().getResultMap(tableInfo.getResultMap());
|
||||||
}
|
}
|
||||||
TableInfo infoDTO = MPJTableInfoHelper.getTableInfo(resultType);
|
MPJTableInfo infoDTO = MPJTableInfoHelper.getTableInfo(resultType);
|
||||||
if (infoDTO == null) {
|
if (infoDTO == null) {
|
||||||
infoDTO = MPJTableInfoHelper.initTableInfo(ms.getConfiguration(),
|
infoDTO = MPJTableInfoHelper.initTableInfo(ms.getConfiguration(),
|
||||||
ms.getId().substring(0, ms.getId().lastIndexOf(".")), resultType);
|
ms.getId().substring(0, ms.getId().lastIndexOf(".")), resultType, null);
|
||||||
}
|
}
|
||||||
if (infoDTO.isAutoInitResultMap()) {
|
if (infoDTO.getTableInfo().isAutoInitResultMap()) {
|
||||||
return ms.getConfiguration().getResultMap(infoDTO.getResultMap());
|
return ms.getConfiguration().getResultMap(infoDTO.getTableInfo().getResultMap());
|
||||||
}
|
}
|
||||||
return new ResultMap.Builder(ms.getConfiguration(), ms.getId(), resultType, EMPTY_RESULT_MAPPING).build();
|
return new ResultMap.Builder(ms.getConfiguration(), ms.getId(), resultType, EMPTY_RESULT_MAPPING).build();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
com.github.yulichang.interceptor.MPJInterceptor,\
|
com.github.yulichang.interceptor.MPJInterceptor,\
|
||||||
com.github.yulichang.injector.MPJSqlInjector,\
|
com.github.yulichang.injector.MPJSqlInjector,\
|
||||||
com.github.yulichang.config.InterceptorConfig
|
com.github.yulichang.config.InterceptorConfig,\
|
||||||
|
com.github.yulichang.toolkit.SpringContentUtils
|
||||||
|
Loading…
x
Reference in New Issue
Block a user