注解映射重构

This commit is contained in:
yulichang 2023-05-09 11:01:30 +08:00
parent 14d7e954b0
commit c5573a39cd
29 changed files with 614 additions and 1116 deletions

View File

@ -42,13 +42,4 @@
<github.global.server>github</github.global.server>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-core</artifactId>
<version>3.5.3.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -10,7 +10,7 @@ import java.lang.annotation.*;
* @since 1.2.0
*/
@Documented
@SuppressWarnings("unused")
@SuppressWarnings({"unused"})
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface EntityMapping {
@ -40,25 +40,6 @@ public @interface EntityMapping {
*/
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);

View File

@ -10,7 +10,7 @@ import java.lang.annotation.*;
* @since 1.2.0
*/
@Documented
@SuppressWarnings("unused")
@SuppressWarnings({"unused"})
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface FieldMapping {
@ -45,25 +45,6 @@ public @interface FieldMapping {
*/
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);

View File

@ -1,6 +1,7 @@
package com.github.yulichang.annotation;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.github.yulichang.annotation.enums.SqlKeyword;
/**
* 映射表条件

View File

@ -0,0 +1,27 @@
package com.github.yulichang.annotation.enums;
/**
* @author yulichang
* @since 1.4.5
*/
public enum SqlKeyword {
NOT,
IN,
NOT_IN,
LIKE,
NOT_LIKE,
EQ,
NE,
GT,
GE,
LT,
LE,
IS_NULL,
IS_NOT_NULL,
BETWEEN,
NOT_BETWEEN,
;
SqlKeyword() {
}
}

View File

@ -65,6 +65,7 @@ public class MybatisPlusJoinAutoConfiguration {
ConfigProperties.joinPrefix = properties.getJoinPrefix();
ConfigProperties.logicDelType = "where".equalsIgnoreCase(properties.getLogicDelType()) ?
LogicDelTypeEnum.WHERE : LogicDelTypeEnum.ON;
ConfigProperties.mappingMaxCount = properties.getMappingMaxCount();
}
/**

View File

@ -44,4 +44,9 @@ public class MybatisPlusJoinProperties {
* 逻辑删除类型 支持 where on
*/
private String logicDelType = "where";
/**
* 映射查询最大深度
*/
private int mappingMaxCount = 5;
}

View File

@ -43,6 +43,12 @@
"defaultValue": "where",
"type": "java.lang.String",
"description": "逻辑删除的位置支持where和on两个."
},
{
"name": "mybatis-plus-join.mapping-max-count",
"defaultValue": 5,
"type": "java.lang.Integer",
"description": "映射查询最大深度."
}
],
"hints": [

View File

@ -14,7 +14,7 @@ import java.util.Map;
*
* @author yulichang
*/
@SuppressWarnings({"unused", "unchecked"})
@SuppressWarnings({"unused"})
public interface MPJBaseService<T> extends IService<T> {

View File

@ -30,6 +30,10 @@ public class ConfigProperties {
* 逻辑删除类型 支持 where on
*/
public static LogicDelTypeEnum logicDelType = LogicDelTypeEnum.WHERE;
/**
* 逻辑删除类型 支持 where on
*/
public static int mappingMaxCount = 5;
/**
* TableInfo适配器
*/

View File

@ -31,6 +31,7 @@ public interface TableAlias extends Constants, MPJBaseMethod {
* 复制tableInfo对象
* 由于各个版本的MP的TableInfo对象存在差异为了兼容性采用反射而不是getter setter
*/
@SuppressWarnings("JavaReflectionMemberAccess")
default TableInfo copyAndSetTableName(TableInfo tableInfo, String tableName) {
try {
TableInfo table;

View File

@ -1,413 +0,0 @@
package com.github.yulichang.extension.mapping.base;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.yulichang.extension.mapping.mapper.MPJTableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.extension.mapping.mapper.MPJTableFieldInfo;
import com.github.yulichang.extension.mapping.mapper.MPJTableInfo;
import com.github.yulichang.extension.mapping.wrapper.MappingQuery;
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 mpjQueryMapping(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 mpjQueryMapping(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 mpjQueryMapping(selectById(id), property);
}
/**
* 查询根据ID 批量查询
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
default List<T> selectBatchIdsDeep(Collection<? extends Serializable> idList) {
return mpjQueryMapping(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 mpjQueryMapping(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 mpjQueryMapping(selectBatchIds(idList), property);
}
/**
* 查询根据 columnMap 条件
*
* @param columnMap 表字段 map 对象
*/
default List<T> selectByMapDeep(Map<String, Object> columnMap) {
return mpjQueryMapping(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 mpjQueryMapping(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 mpjQueryMapping(selectByMap(columnMap), property);
}
/**
* 根据 entity 条件查询一条记录
*
* @param queryWrapper 实体对象封装操作类可以为 null
*/
default T selectOneDeep(Wrapper<T> queryWrapper) {
return mpjQueryMapping(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 mpjQueryMapping(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 mpjQueryMapping(selectOne(queryWrapper), property);
}
/**
* 根据 entity 条件查询全部记录
*
* @param queryWrapper 实体对象封装操作类可以为 null
*/
default List<T> selectListDeep(Wrapper<T> queryWrapper) {
return mpjQueryMapping(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 mpjQueryMapping(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 mpjQueryMapping(selectList(queryWrapper), 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);
mpjQueryMapping(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);
mpjQueryMapping(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);
mpjQueryMapping(e.getRecords(), property);
return e;
}
/**
* 查询映射关系<br/>
* 对结果进行二次查询<br/>
* 可以自行查询然后在通过此方法进行二次查询<br/>
* list为null或空会查询全部映射关系<br/>
*
* @param t 第一次查询结果
*/
default <R> T mpjQueryMapping(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 = MappingQuery.mpjQueryList(fieldInfo.getJoinMapper(),
fieldInfo.isFieldIsMap(), SqlKeyword.EQ, fieldInfo.getJoinColumn(), obj, fieldInfo);
mpjBindData(t, fieldInfo, joinList);
fieldInfo.removeJoinField(joinList);
}
}
}
}
return t;
}
/**
* 查询映射关系<br/>
* 对结果进行二次查询<br/>
* 可以自行查询然后在通过此方法进行二次查询<br/>
* list为null或空会查询全部映射关系<br/>
*
* @param map 第一次查询结果
*/
default <R> Map<String, Object> mpjQueryMapMapping(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 = MappingQuery.mpjQueryList(fieldInfo.getJoinMapper(),
fieldInfo.isFieldIsMap(), SqlKeyword.EQ, fieldInfo.getJoinColumn(), obj, fieldInfo);
mpjBindMap(map, fieldInfo, joinList);
fieldInfo.removeJoinField(joinList);
}
}
}
}
return map;
}
/**
* 查询映射关系<br/>
* 对结果进行二次查询<br/>
* 可以自行查询然后在通过此方法进行二次查询<br/>
* list为null或空会查询全部映射关系<br/>
*
* @param list 第一次查询结果
*/
default <R> List<T> mpjQueryMapping(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 = MappingQuery.mpjQueryList(fieldInfo.getJoinMapper(),
fieldInfo.isMappingEntity() && fieldInfo.isFieldIsMap(), SqlKeyword.IN,
fieldInfo.getJoinColumn(), itemList, fieldInfo);
list.forEach(i -> mpjBindData(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>> mpjQueryMapMapping(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 = MappingQuery.mpjQueryList(fieldInfo.getJoinMapper(),
fieldInfo.isMappingEntity() && fieldInfo.isFieldIsMap(), SqlKeyword.IN,
fieldInfo.getJoinColumn(), itemList, fieldInfo);
list.forEach(i -> mpjBindMap(i, fieldInfo, joinList));
fieldInfo.removeJoinField(joinList);
} else {
list.forEach(i -> i.put(fieldInfo.getField().getName(), new ArrayList<>()));
}
}
}
}
return list;
}
/**
* 绑定数据
*/
default void mpjBindData(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 mpjBindMap(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);
}
}

View File

@ -0,0 +1,244 @@
package com.github.yulichang.extension.mapping.base;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.github.yulichang.annotation.EntityMapping;
import com.github.yulichang.annotation.FieldMapping;
import com.github.yulichang.extension.mapping.config.DeepConfig;
import com.github.yulichang.extension.mapping.relation.Relation;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
/**
* 深度查询
* <p>
* 对配置了映射注解的字段进行查询
* 目前查询深度只支持2级(只解析当前实体类的映射注解,不会对查询结果再次解析注解)
* 多级查询可能存在循环引用的问题也可能会导致全量查询
*
* @author yulichang
* @see EntityMapping
* @see FieldMapping
* @since 1.2.0
*/
@SuppressWarnings({"unused"})
public interface MPJDeepService<T> extends IService<T> {
/**
* 根据 ID 查询 并关联全部映射
*
* @param id 主键ID
*/
default T getByIdDeep(Serializable id) {
return Relation.mpjGetRelation(getById(id), DeepConfig.defaultConfig());
}
/**
* 根据 ID 查询 并关联指定映射
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param id 主键ID
* @param config 映射配置
*/
default <R> T getByIdDeep(Serializable id, Function<DeepConfig.Builder<T>, DeepConfig.Builder<T>> config) {
return Relation.mpjGetRelation(getById(id), config.apply(DeepConfig.builder()).build());
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectByIdDeep(1, Arrays.asList(User::getId, ... ))
*
* @param id 主键ID
* @param config 映射配置
*/
default <R> T getByIdDeep(Serializable id, DeepConfig<T> config) {
return Relation.mpjGetRelation(getById(id), config);
}
/**
* 查询根据ID 批量查询
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
default List<T> listByIdsDeep(Collection<? extends Serializable> idList) {
return Relation.mpjGetRelation(listByIds(idList), DeepConfig.defaultConfig());
}
/**
* 查询根据ID 批量查询
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
* @param config 映射配置
*/
default <R> List<T> listByIdsDeep(Collection<? extends Serializable> idList, Function<DeepConfig.Builder<T>, DeepConfig.Builder<T>> config) {
return Relation.mpjGetRelation(listByIds(idList), config.apply(DeepConfig.builder()).build());
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectBatchIdsDeep(idList, Arrays.asList(User::getId, ... ))
*
* @param idList 主键ID列表(不能为 null 以及 empty)
* @param config 映射配置
*/
default <R> List<T> listByIdsDeep(Collection<? extends Serializable> idList, DeepConfig<T> config) {
return Relation.mpjGetRelation(listByIds(idList), config);
}
/**
* 查询根据 columnMap 条件
*
* @param columnMap 表字段 map 对象
*/
default List<T> listByMapDeep(Map<String, Object> columnMap) {
return Relation.mpjGetRelation(listByMap(columnMap), DeepConfig.defaultConfig());
}
/**
* 查询根据 columnMap 条件
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param columnMap 表字段 map 对象
* @param config 映射配置
*/
default <R> List<T> listByMapDeep(Map<String, Object> columnMap, Function<DeepConfig.Builder<T>, DeepConfig.Builder<T>> config) {
return Relation.mpjGetRelation(listByMap(columnMap), config.apply(DeepConfig.builder()).build());
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectByMapDeep(columnMap, Arrays.asList(User::getId, ... ))
*
* @param columnMap 表字段 map 对象
* @param config 映射配置
*/
default <R> List<T> listByMapDeep(Map<String, Object> columnMap, DeepConfig<T> config) {
return Relation.mpjGetRelation(listByMap(columnMap), config);
}
/**
* 根据 entity 条件查询一条记录
*
* @param queryWrapper 实体对象封装操作类可以为 null
*/
default T getOneDeep(Wrapper<T> queryWrapper) {
return Relation.mpjGetRelation(getOne(queryWrapper), DeepConfig.defaultConfig());
}
/**
* 根据 entity 条件查询一条记录
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param queryWrapper 实体对象封装操作类可以为 null
* @param config 映射配置
*/
default <R> T getOneDeep(Wrapper<T> queryWrapper, Function<DeepConfig.Builder<T>, DeepConfig.Builder<T>> config) {
return Relation.mpjGetRelation(getOne(queryWrapper), config.apply(DeepConfig.builder()).build());
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectOneDeep(queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param queryWrapper 实体对象封装操作类可以为 null
* @param config 映射配置
*/
default <R> T getOneDeep(Wrapper<T> queryWrapper, DeepConfig<T> config) {
return Relation.mpjGetRelation(getOne(queryWrapper), config);
}
/**
* 根据 entity 条件查询全部记录
*
* @param queryWrapper 实体对象封装操作类可以为 null
*/
default List<T> listDeep(Wrapper<T> queryWrapper) {
return Relation.mpjGetRelation(list(queryWrapper), DeepConfig.defaultConfig());
}
/**
* 根据 entity 条件查询全部记录
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param queryWrapper 实体对象封装操作类可以为 null
* @param config 映射配置
*/
default <R> List<T> listDeep(Wrapper<T> queryWrapper, Function<DeepConfig.Builder<T>, DeepConfig.Builder<T>> config) {
return Relation.mpjGetRelation(list(queryWrapper), config.apply(DeepConfig.builder()).build());
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectListDeep(queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param queryWrapper 实体对象封装操作类可以为 null
* @param config 映射配置
*/
default <R> List<T> listDeep(Wrapper<T> queryWrapper, DeepConfig<T> config) {
return Relation.mpjGetRelation(list(queryWrapper), config);
}
/**
* 根据 entity 条件查询全部记录并翻页
*
* @param page 分页查询条件可以为 RowBounds.DEFAULT
* @param queryWrapper 实体对象封装操作类可以为 null
*/
default <E extends IPage<T>> E pageDeep(E page, Wrapper<T> queryWrapper) {
E e = page(page, queryWrapper);
Relation.mpjGetRelation(e.getRecords(), DeepConfig.defaultConfig());
return e;
}
/**
* 根据 entity 条件查询全部记录并翻页
* <p>
* JDK 默认不推荐泛型数组会引起 Java堆污染(Heap Pollution)
*
* @param page 分页查询条件可以为 RowBounds.DEFAULT
* @param queryWrapper 实体对象封装操作类可以为 null
* @param config 映射配置
*/
default <R, E extends IPage<T>> E pageDeep(E page, Wrapper<T> queryWrapper, Function<DeepConfig.Builder<T>, DeepConfig.Builder<T>> config) {
E e = page(page, queryWrapper);
Relation.mpjGetRelation(e.getRecords(), config.apply(DeepConfig.builder()).build());
return e;
}
/**
* 针对可变参数堆污染提供的重载
* list为null或空会查询全部映射关系
* <p>
* selectPageDeep(page, queryWrapper, Arrays.asList(User::getId, ... ))
*
* @param page 分页查询条件可以为 RowBounds.DEFAULT
* @param queryWrapper 实体对象封装操作类可以为 null
* @param config 映射配置
*/
default <R, E extends IPage<T>> E pageDeep(E page, Wrapper<T> queryWrapper, DeepConfig<T> config) {
E e = page(page, queryWrapper);
Relation.mpjGetRelation(e.getRecords(), config);
return e;
}
}

View File

@ -0,0 +1,61 @@
package com.github.yulichang.extension.mapping.base;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.github.yulichang.annotation.EntityMapping;
import com.github.yulichang.annotation.FieldMapping;
import com.github.yulichang.extension.mapping.config.DeepConfig;
import com.github.yulichang.extension.mapping.relation.Relation;
import java.util.function.Function;
/**
* 深度查询
* <p>
* 对配置了映射注解的字段进行查询
* 目前查询深度只支持2级(只解析当前实体类的映射注解,不会对查询结果再次解析注解)
* 多级查询可能存在循环引用的问题也可能会导致全量查询
* 用于替换deep
*
* @author yulichang
* @see EntityMapping
* @see FieldMapping
* @since 1.4.4
*/
@SuppressWarnings({"unchecked", "unused"})
public interface MPJRelationService<T> extends IService<T> {
/**
* 通过注解实现单表多次查询
*
* @param function BaseMapper调用方法
* @see com.github.yulichang.annotation.EntityMapping
* @see com.github.yulichang.annotation.FieldMapping
*/
default <R, M extends BaseMapper<T>> R getRelation(Function<M, R> function) {
return Relation.mpjGetRelation(function.apply((M) getBaseMapper()), DeepConfig.defaultConfig());
}
/**
* 通过注解实现单表多次查询
*
* @param function BaseMapper调用方法
* @see com.github.yulichang.annotation.EntityMapping
* @see com.github.yulichang.annotation.FieldMapping
*/
default <R, M extends BaseMapper<T>> R getRelation(Function<M, R> function, DeepConfig<T> config) {
return Relation.mpjGetRelation(function.apply((M) getBaseMapper()), config);
}
/**
* 通过注解实现单表多次查询
*
* @param function BaseMapper调用方法
* @param config 映射配置
* @see com.github.yulichang.annotation.EntityMapping
* @see com.github.yulichang.annotation.FieldMapping
*/
default <R, M extends BaseMapper<T>> R getRelation(Function<M, R> function, Function<DeepConfig.Builder<T>, DeepConfig.Builder<T>> config) {
return Relation.mpjGetRelation(function.apply((M) getBaseMapper()), config.apply(DeepConfig.builder()).build());
}
}

View File

@ -1,556 +0,0 @@
package com.github.yulichang.extension.mapping.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.extension.mapping.base.MPJDeepMapper;
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 ((MPJDeepMapper<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 ((MPJDeepMapper<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 ((MPJDeepMapper<T>) getBaseMapper()).selectByIdDeep(id, property);
}
/**
* 查询根据ID 批量查询
*
* @param idList 主键ID列表
*/
default List<T> listByIdsDeep(Collection<? extends Serializable> idList) {
return ((MPJDeepMapper<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 ((MPJDeepMapper<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 ((MPJDeepMapper<T>) getBaseMapper()).selectBatchIdsDeep(idList, property);
}
/**
* 查询根据 columnMap 条件
*
* @param columnMap 表字段 map 对象
*/
default List<T> listByMapDeep(Map<String, Object> columnMap) {
return ((MPJDeepMapper<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 ((MPJDeepMapper<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 ((MPJDeepMapper<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 ((MPJDeepMapper<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 ((MPJDeepMapper<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 ((MPJDeepMapper<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 ((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapping(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 ((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapping(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 ((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapping(getOne(queryWrapper, throwEx), property);
}
/**
* 根据 Wrapper查询一条记录
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default Map<String, Object> getMapDeep(Wrapper<T> queryWrapper) {
return ((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(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 ((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(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 ((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(getMap(queryWrapper), currentModelClass(), property);
}
/**
* 查询列表
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
default List<T> listDeep(Wrapper<T> queryWrapper) {
return ((MPJDeepMapper<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 ((MPJDeepMapper<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 ((MPJDeepMapper<T>) getBaseMapper()).selectListDeep(queryWrapper, property);
}
/**
* 查询所有
*
* @see Wrappers#emptyWrapper()
*/
default List<T> listDeep() {
return ((MPJDeepMapper<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 ((MPJDeepMapper<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 ((MPJDeepMapper<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);
((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapping(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);
((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapping(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);
((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapping(e.getRecords(), property);
return e;
}
/**
* 无条件翻页查询
*
* @param page 翻页对象
* @see Wrappers#emptyWrapper()
*/
default <E extends IPage<T>> E pageDeep(E page) {
E e = page(page);
((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapping(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);
((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapping(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);
((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapping(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 ((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(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 ((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(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 ((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(listMaps(queryWrapper), currentModelClass(), property);
}
/**
* 查询所有列表
*
* @see Wrappers#emptyWrapper()
*/
default List<Map<String, Object>> listMapsDeep() {
return ((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(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 ((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(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 ((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(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);
((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(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);
((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(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);
((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(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);
((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(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);
((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(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);
((MPJDeepMapper<T>) getBaseMapper()).mpjQueryMapMapping(e.getRecords(), currentModelClass(), property);
return e;
}
}

View File

@ -0,0 +1,73 @@
package com.github.yulichang.extension.mapping.config;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.config.ConfigProperties;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* 映射查询配置
*
* @author yulichang
* @since 1.4.5
*/
@Accessors(chain = true)
public class DeepConfig<T> {
private static final DeepConfig<?> defaultConfig = new DeepConfig<>();
@Getter
@Setter
private List<SFunction<T, ?>> prop;
@Getter
@Setter
private boolean loop = false;
@Getter
@Setter
private int maxCount = ConfigProperties.mappingMaxCount;
public static <T> Builder<T> builder() {
return new Builder<>();
}
@SuppressWarnings("unchecked")
public static <T> DeepConfig<T> defaultConfig() {
return (DeepConfig<T>) defaultConfig;
}
public static class Builder<T> {
private final DeepConfig<T> conf = new DeepConfig<>();
@SafeVarargs
public final Builder<T> prop(SFunction<T, ?>... prop) {
if (Objects.isNull(conf.prop)) {
conf.prop = new ArrayList<>();
}
conf.prop.addAll(Arrays.asList(prop));
return this;
}
public Builder<T> loop(boolean loop) {
conf.loop = loop;
return this;
}
public Builder<T> maxCount(int maxCount) {
conf.maxCount = maxCount;
return this;
}
public DeepConfig<T> build() {
return conf;
}
}
}

View File

@ -16,5 +16,4 @@ public class MappingConfig {
TableInfoHelper.getTableInfos().forEach(i ->
MPJTableInfoHelper.initTableInfo(i.getEntityType(), MPJTableMapperHelper.getMapper(i.getEntityType())));
}
}

View File

@ -12,6 +12,7 @@ import lombok.Getter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* 关联查询条件
@ -67,7 +68,7 @@ public class MPJMappingWrapper {
if (this.hasCondition) {
this.conditionList = new ArrayList<>();
for (MPJMappingCondition condition : conditions) {
conditionList.add(new Condition(condition.keyWord(), condition.column(), condition.value()));
conditionList.add(new Condition(convert(condition.keyWord()), condition.column(), condition.value()));
}
}
@ -87,6 +88,46 @@ public class MPJMappingWrapper {
}
}
private SqlKeyword convert(com.github.yulichang.annotation.enums.SqlKeyword sqlKeyword) {
if (Objects.isNull(sqlKeyword)) {
return null;
}
switch (sqlKeyword) {
case NOT:
return SqlKeyword.NOT;
case IN:
return SqlKeyword.IN;
case NOT_IN:
return SqlKeyword.NOT_IN;
case LIKE:
return SqlKeyword.LIKE;
case NOT_LIKE:
return SqlKeyword.NOT_LIKE;
case EQ:
return SqlKeyword.EQ;
case NE:
return SqlKeyword.NE;
case GT:
return SqlKeyword.GT;
case GE:
return SqlKeyword.GE;
case LT:
return SqlKeyword.LT;
case LE:
return SqlKeyword.LE;
case IS_NULL:
return SqlKeyword.IS_NULL;
case IS_NOT_NULL:
return SqlKeyword.IS_NOT_NULL;
case BETWEEN:
return SqlKeyword.BETWEEN;
case NOT_BETWEEN:
return SqlKeyword.NOT_BETWEEN;
default:
return SqlKeyword.EQ;
}
}
@Getter
@AllArgsConstructor
public static class Apply {

View File

@ -60,10 +60,6 @@ public class MPJTableFieldInfo {
* 属性名
*/
private String property;
/**
* 数据结构是否是Map或者List<Map>
*/
private boolean fieldIsMap;
/**
* 属性是否是集合
*/
@ -80,10 +76,6 @@ public class MPJTableFieldInfo {
* 当前字段信息
*/
private String thisColumn;
/**
* 当前字段信息
*/
private String thisMapKey;
/**
* 映射实体类
*/
@ -100,12 +92,6 @@ public class MPJTableFieldInfo {
* 映射属性字段
*/
private Field joinField;
/**
* fieldIsMap 为true时使用
* 映射查询Map 的key
* 默认为 关联字段的数据库列名
*/
private String joinMapKey;
/**
* 关联的mapper引用
*/
@ -123,16 +109,16 @@ public class MPJTableFieldInfo {
* 初始化关联字段信息
*/
public MPJTableFieldInfo(Class<?> entityType, EntityMapping mapping, Field field) {
this.entityType = entityType;
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());
initThisField(mapping.thisField());
initJoinField(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 :
@ -141,6 +127,7 @@ public class MPJTableFieldInfo {
}
public MPJTableFieldInfo(Class<?> entityType, FieldMapping mappingField, Field field) {
this.entityType = entityType;
this.isMappingEntity = false;
this.isMappingField = true;
field.setAccessible(true);
@ -151,10 +138,9 @@ public class MPJTableFieldInfo {
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());
initThisField(mappingField.thisField());
initJoinField(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(),
@ -178,7 +164,7 @@ public class MPJTableFieldInfo {
this.bindField = field;
}
private void initJoinField(String joinMapKey, String joinField) {
private void initJoinField(String joinField) {
if (StringUtils.isNotBlank(joinField)) {
this.joinProperty = joinField;
} else {
@ -205,10 +191,9 @@ public class MPJTableFieldInfo {
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) {
private void initThisField(String thisField) {
if (StringUtils.isNotBlank(thisField)) {
this.thisProperty = thisField;
} else {
@ -233,7 +218,6 @@ public class MPJTableFieldInfo {
this.thisColumn = fieldInfo.getColumn();
}
this.thisField.setAccessible(true);
this.thisMapKey = StringUtils.isBlank(thisMapKey) ? this.thisColumn : thisMapKey;
}
private void initField(Field field) {
@ -245,30 +229,26 @@ public class MPJTableFieldInfo {
throw new MPJException("对多关系的数据结构目前只支持 <List> 暂不支持其他Collection实现 " + this.field.getType().getTypeName());
}
if (Map.class.isAssignableFrom(field.getType())) {
this.fieldIsMap = true;
throw ExceptionUtils.mpe("映射查询不支持Map结构 <%s.%s>", this.entityType.getSimpleName(), field.getName());
} 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;
if (((ParameterizedType) type).getRawType() == Map.class) {
throw ExceptionUtils.mpe("映射查询不支持Map结构 <%s.%s>", this.entityType.getSimpleName(), field.getName());
}
}
} 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();
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();
}
}
@ -338,14 +318,9 @@ public class MPJTableFieldInfo {
}
}
@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);
}
joinList.forEach(this::joinFieldSetNull);
}
}
@ -361,17 +336,4 @@ public class MPJTableFieldInfo {
}
}
}
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

@ -1,23 +1,77 @@
package com.github.yulichang.extension.mapping.relation;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.github.yulichang.extension.mapping.mapper.MPJTableInfoHelper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.config.ConfigProperties;
import com.github.yulichang.extension.mapping.config.DeepConfig;
import com.github.yulichang.extension.mapping.mapper.MPJTableFieldInfo;
import com.github.yulichang.extension.mapping.mapper.MPJTableInfo;
import com.github.yulichang.extension.mapping.mapper.MPJTableInfoHelper;
import com.github.yulichang.extension.mapping.wrapper.MappingQuery;
import com.github.yulichang.toolkit.LambdaUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
@SuppressWarnings("all")
@SuppressWarnings("unchecked")
public class Relation {
/**
* 通过注解实现单表多次查询
*
* @param r BaseMapper执行结果
* @param config 映射配置
* @see com.github.yulichang.annotation.EntityMapping
* @see com.github.yulichang.annotation.FieldMapping
*/
public static <R, T> R mpjGetRelation(R r, DeepConfig<T> config) {
int start = ConfigProperties.mappingMaxCount - config.getMaxCount();
if (Objects.isNull(r)) {
return null;
} else if (r instanceof List) {
List<T> data = (List<T>) r;
if (CollectionUtils.isEmpty(data)) {
return r;
} else {
T t = data.get(0);
if (Map.class.isAssignableFrom(t.getClass())) {
throw ExceptionUtils.mpe("暂不支持Map类型映射");
}
if (Object.class == t.getClass()) {
return r;
}
return (R) Relation.list(data, config.getProp(), config.isLoop(), start);
}
} else if (r instanceof IPage) {
IPage<T> data = (IPage<T>) r;
if (!CollectionUtils.isEmpty(data.getRecords())) {
T t = data.getRecords().get(0);
if (Map.class.isAssignableFrom(t.getClass())) {
throw ExceptionUtils.mpe("暂不支持Map类型映射");
}
if (Object.class == t.getClass()) {
return r;
}
Relation.list(data.getRecords(), config.getProp(), config.isLoop(), start);
}
return r;
} else if (r instanceof Integer) {
return r;
} else if (r instanceof Long) {
return r;
} else if (r instanceof Boolean) {
return r;
} else if (Object.class == r.getClass()) {
return r;
} else {
return (R) Relation.one((T) r, config.getProp(), config.isLoop(), start);
}
}
public static <T> List<T> list(List<T> data, List<SFunction<T, ?>> property) {
public static <T> List<T> list(List<T> data, List<SFunction<T, ?>> property, boolean loop, int count) {
if (CollectionUtils.isEmpty(data)) {
return data;
}
@ -31,10 +85,9 @@ public class Relation {
if (!hasProperty || listProperty.contains(fieldInfo.getProperty())) {
List<Object> itemList = data.stream().map(fieldInfo::thisFieldGet).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(itemList)) {
List<?> joinList = MappingQuery.mpjQueryList(fieldInfo.getJoinMapper(),
fieldInfo.isMappingEntity() && fieldInfo.isFieldIsMap(), SqlKeyword.IN,
List<?> joinList = MappingQuery.mpjQueryList(fieldInfo.getJoinMapper(), SqlKeyword.IN,
fieldInfo.getJoinColumn(), itemList, fieldInfo);
data.forEach(i -> mpjBindData(i, fieldInfo, joinList));
data.forEach(i -> mpjBindData(i, property, fieldInfo, joinList, loop, count));
fieldInfo.removeJoinField(joinList);
if (CollectionUtils.isEmpty(joinList)) {
continue;
@ -57,7 +110,7 @@ public class Relation {
*
* @param t 第一次查询结果
*/
public static <T> T one(T t, List<SFunction<T, ?>> property) {
public static <T> T one(T t, List<SFunction<T, ?>> property, boolean loop, int count) {
if (t == null) {
return null;
}
@ -70,9 +123,9 @@ public class Relation {
if (!hasProperty || list.contains(fieldInfo.getProperty())) {
Object obj = fieldInfo.thisFieldGet(t);
if (obj != null) {
List<?> joinList = MappingQuery.mpjQueryList(fieldInfo.getJoinMapper(),
fieldInfo.isFieldIsMap(), SqlKeyword.EQ, fieldInfo.getJoinColumn(), obj, fieldInfo);
mpjBindData(t, fieldInfo, joinList);
List<?> joinList = MappingQuery.mpjQueryList(fieldInfo.getJoinMapper(), SqlKeyword.EQ,
fieldInfo.getJoinColumn(), obj, fieldInfo);
mpjBindData(t, property, fieldInfo, joinList, loop, count);
fieldInfo.removeJoinField(joinList);
}
}
@ -81,11 +134,23 @@ public class Relation {
return t;
}
public static <R> void mpjBindData(R t, MPJTableFieldInfo fieldInfo, List<?> joinList) {
public static <R, T, E> void mpjBindData(R t, List<SFunction<T, ?>> property, MPJTableFieldInfo fieldInfo, List<?> joinList, boolean loop, int count) {
if (fieldInfo.isMappingEntity()) {
List<?> list = joinList.stream().filter(j -> fieldInfo.joinFieldGet(j).equals(fieldInfo.thisFieldGet(t)))
if (count > ConfigProperties.mappingMaxCount) {
throw ExceptionUtils.mpe("超过最大查询深度");
}
List<E> list = (List<E>) joinList.stream().filter(j -> fieldInfo.joinFieldGet(j).equals(fieldInfo.thisFieldGet(t)))
.collect(Collectors.toList());
MPJTableFieldInfo.bind(fieldInfo, t, list);
if (loop && CollectionUtils.isNotEmpty(list)) {
int newCount = count + 1;
if (CollectionUtils.isNotEmpty(property) && LambdaUtils.getEntityClass(property.get(0)).isAssignableFrom(list.get(0).getClass())) {
List<SFunction<E, ?>> property1 = ((List<SFunction<E, ?>>) ((Object) property));
list(list, property1, loop, count);
} else {
list(list, Collections.EMPTY_LIST, loop, newCount);
}
}
}
if (fieldInfo.isMappingField()) {
MPJTableFieldInfo.bind(fieldInfo, t, joinList.stream().filter(j -> fieldInfo.joinFieldGet(j).equals(

View File

@ -22,7 +22,7 @@ public class MappingQuery<T> extends QueryWrapper<T> {
* 映射 wrapper 构造器
* 仅对使用映射注解时使用
*/
public static <T> List<?> mpjQueryList(BaseMapper<T> baseMapper, boolean selectMap, SqlKeyword keyword,
public static <T> List<?> mpjQueryList(BaseMapper<T> baseMapper, SqlKeyword keyword,
String column, Object val, MPJTableFieldInfo fieldInfo) {
MPJMappingWrapper infoWrapper = fieldInfo.getWrapper();
MappingQuery<T> wrapper = new MappingQuery<>();
@ -63,9 +63,6 @@ public class MappingQuery<T> extends QueryWrapper<T> {
if (infoWrapper.isHasApply()) {
infoWrapper.getApplyList().forEach(a -> wrapper.apply(a.getSql(), (Object[]) a.getVal()));
}
if (selectMap) {
return baseMapper.selectMaps(wrapper);
}
return baseMapper.selectList(wrapper);
}
}

View File

@ -1,7 +1,9 @@
package com.github.yulichang.test.join;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.github.yulichang.test")
@ -9,7 +11,9 @@ import org.springframework.context.annotation.ComponentScan;
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
ISqlInjector bean = run.getBean(ISqlInjector.class);
System.out.println(bean);
}
}

View File

@ -5,11 +5,13 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.github.yulichang.annotation.DynamicTableName;
import com.github.yulichang.annotation.EntityMapping;
import com.github.yulichang.test.join.enums.Sex;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;
import lombok.experimental.FieldNameConstants;
import java.io.Serializable;
import java.time.LocalDateTime;
@ -21,6 +23,7 @@ import java.util.Map;
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@DynamicTableName
@FieldNameConstants
@TableName(value = "`user`", autoResultMap = true)
public class UserDO extends ID<Integer> implements Serializable {
@ -56,7 +59,6 @@ public class UserDO extends ID<Integer> implements Serializable {
@TableField(exist = false)
private String updateName;
@TableField(exist = false)
private String alias;

View File

@ -1,13 +1,12 @@
package com.github.yulichang.test.join.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import com.github.yulichang.extension.mapping.base.MPJDeepMapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface MyBaseMapper<T> extends MPJBaseMapper<T>, MPJDeepMapper<T> {
public interface MyBaseMapper<T> extends MPJBaseMapper<T> {
@SuppressWarnings("UnusedReturnValue")
int insertBatchSomeColumn(List<T> entityList);

View File

@ -16,7 +16,9 @@ import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.DeleteJoinWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.github.yulichang.wrapper.UpdateJoinWrapper;
import org.h2.engine.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.BadSqlGrammarException;
@ -120,6 +122,7 @@ class LambdaWrapperTest {
" AND t1.del = false\n" +
" AND (t.id <= ?)\n" +
"ORDER BY t.id DESC");
String s = UserDO.Fields.addressId;
MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
.selectAll(UserDO.class)

View File

@ -0,0 +1,8 @@
package com.github.yulichang.test.mapping.service;
import com.github.yulichang.extension.mapping.base.MPJDeepService;
import com.github.yulichang.extension.mapping.base.MPJRelationService;
import com.github.yulichang.test.mapping.entity.UserDO;
public interface UserService extends MPJDeepService<UserDO>, MPJRelationService<UserDO> {
}

View File

@ -0,0 +1,11 @@
package com.github.yulichang.test.mapping.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.test.mapping.entity.UserDO;
import com.github.yulichang.test.mapping.mapper.UserMapper;
import com.github.yulichang.test.mapping.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements UserService {
}

View File

@ -29,21 +29,21 @@ INSERT INTO area (id, province, city, area, postcode, del) VALUES (10022, '北
DELETE FROM `user`;
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 1, 1, '{"aa":"aaa","bb":"bbb"}', 1, 1, 'https://url-01', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 1, null, '{"aa":"aaa","bb":"bbb"}', 1, 1, 'https://url-01', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 2, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-02', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 3, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-03', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 4, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-04', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 5, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-05', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 6, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-06', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 7, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-07', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 8, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-08', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 3, 2, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-03', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 4, 3, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-04', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 5, 4, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-05', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 6, 5, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-06', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 7, 6, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-07', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 8, 7, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-08', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES ( 9, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-09', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES (10, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-10', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES (11, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-11', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES (12, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-12', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES (13, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-13', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES (14, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-14', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES (15, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-15', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES (14, 7, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-14', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES (15, 7, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-15', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES (16, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-16', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES (17, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-17', false);
INSERT INTO `user` (id, pid, `name`, `address_id`, sex, head_img, del) VALUES (18, 1, '{"aa":"aaa","bb":"bbb"}', 1, 0, 'https://url-18', false);

View File

@ -1,15 +1,14 @@
package com.github.yulichang.test.mapping;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.yulichang.test.mapping.entity.AddressDO;
import com.github.yulichang.test.mapping.entity.UserDO;
import com.github.yulichang.test.mapping.mapper.UserMapper;
import com.github.yulichang.test.mapping.service.UserService;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
/**
@ -20,11 +19,12 @@ import java.util.List;
class MappingTest {
@Resource
private UserMapper userMapper;
private UserService userService;
@Test
public void test() {
List<UserDO> dos = userMapper.selectRelation(e -> e.selectList(new QueryWrapper<>()), Collections.singletonList(UserDO::getAddressId));
List<UserDO> dos = userService.getRelation(m -> m.selectList(new LambdaQueryWrapper<UserDO>()
.eq(UserDO::getPid, 5)), conf -> conf.prop(UserDO::getPUser).loop(true).maxCount(100));
System.out.println(1);
}
@ -33,7 +33,7 @@ class MappingTest {
MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
.selectAll(UserDO.class)
.leftJoin(AddressDO.class, AddressDO::getId, UserDO::getAddressId);
List<UserDO> dos = userMapper.selectRelation(e -> e.selectList(wrapper));
List<UserDO> dos = userService.listDeep(wrapper);
System.out.println(1);
}
}