From 9464dea9f2ab9bf77430b43eb37a338c440f2884 Mon Sep 17 00:00:00 2001 From: yulichang <570810310@qq.com> Date: Wed, 16 Nov 2022 18:27:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5=20mybatis=20plus=203.5.2=20?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mybatis-plus-join-annotation/pom.xml | 2 + mybatis-plus-join-boot-starter/pom.xml | 4 +- mybatis-plus-join-core/pom.xml | 9 +- .../yulichang/interceptor/MPJInterceptor.java | 108 ++++--- .../github/yulichang/toolkit/ClassUtils.java | 267 ++++++++++++++++++ .../yulichang/toolkit/InterceptorList.java | 2 +- .../github/yulichang/toolkit/LambdaUtils.java | 65 +++-- .../yulichang/toolkit/MPJReflectionKit.java | 61 ++++ .../yulichang/toolkit/ReflectionKit.java | 84 +++--- .../toolkit/support/ColumnCache.java | 2 +- .../toolkit/support/IdeaProxyLambdaMeta.java | 77 +++++ .../yulichang/toolkit/support/LambdaMeta.java | 39 +++ .../toolkit/support/ReflectLambdaMeta.java | 78 +++++ .../toolkit/support/SelectColumn.java | 2 +- .../toolkit/support/SerializedLambda.java | 128 +++------ .../toolkit/support/ShadowLambdaMeta.java | 46 +++ .../yulichang/wrapper/MPJLambdaWrapper.java | 35 +-- .../wrapper/resultmap/MybatisLabel.java | 28 +- .../yulichang/wrapper/resultmap/Result.java | 2 +- mybatis-plus-join-test/pom.xml | 26 +- .../test/collection/Application.java | 9 + .../test/collection/CollectionTest.java | 47 +++ .../collection/config/MybatisPlusConfig.java | 24 ++ .../test/collection/dto/TableADTO.java | 17 ++ .../test/collection/dto/TableBDTO.java | 19 ++ .../test/collection/dto/TableCDTO.java | 19 ++ .../test/collection/dto/TableDDTO.java | 19 ++ .../test/collection/dto/TableEDTO.java | 15 + .../test/collection/entity/TableA.java | 15 + .../test/collection/entity/TableB.java | 17 ++ .../test/collection/entity/TableC.java | 17 ++ .../test/collection/entity/TableD.java | 17 ++ .../test/collection/entity/TableE.java | 17 ++ .../yulichang/test/collection/enums/Sex.java | 24 ++ .../test/collection/mapper/TableAMapper.java | 10 + .../test/collection/mapper/TableBMapper.java | 11 + .../test/collection/mapper/TableCMapper.java | 11 + .../test/collection/mapper/TableDMapper.java | 11 + .../test/collection/mapper/TableEMapper.java | 11 + .../test/join/LambdaWrapperTest.java | 9 +- .../yulichang/test/join/dto/TableDTO.java | 61 ++++ .../yulichang/test/join/entity/TableA.java | 15 + .../yulichang/test/join/entity/TableB.java | 17 ++ .../yulichang/test/join/entity/TableC.java | 17 ++ .../yulichang/test/join/entity/TableD.java | 17 ++ .../yulichang/test/join/entity/TableE.java | 17 ++ .../yulichang/test/join/entity/UserDO.java | 2 +- .../test/join/mapper/TableAMapper.java | 11 + .../test/join/mapper/TableBMapper.java | 11 + .../test/join/mapper/TableCMapper.java | 11 + .../test/join/mapper/TableDMapper.java | 11 + .../test/join/mapper/TableEMapper.java | 11 + .../mapping/config/MybatisPlusConfig.java | 1 - .../test/resources/application-collection.yml | 5 + .../src/test/resources/application.yml | 1 + .../src/test/resources/db/collection/data.sql | 29 ++ .../test/resources/db/collection/schema.sql | 48 ++++ .../src/test/resources/db/join/data.sql | 3 +- .../src/test/resources/db/join/schema.sql | 20 +- 59 files changed, 1441 insertions(+), 271 deletions(-) create mode 100644 mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/ClassUtils.java create mode 100644 mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/MPJReflectionKit.java create mode 100644 mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/IdeaProxyLambdaMeta.java create mode 100644 mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/LambdaMeta.java create mode 100644 mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ReflectLambdaMeta.java create mode 100644 mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ShadowLambdaMeta.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/Application.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/CollectionTest.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/config/MybatisPlusConfig.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableADTO.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableBDTO.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableCDTO.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableDDTO.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableEDTO.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableA.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableB.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableC.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableD.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableE.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/enums/Sex.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableAMapper.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableBMapper.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableCMapper.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableDMapper.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableEMapper.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/dto/TableDTO.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableA.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableB.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableC.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableD.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableE.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableAMapper.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableBMapper.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableCMapper.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableDMapper.java create mode 100644 mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableEMapper.java create mode 100644 mybatis-plus-join-test/src/test/resources/application-collection.yml create mode 100644 mybatis-plus-join-test/src/test/resources/db/collection/data.sql create mode 100644 mybatis-plus-join-test/src/test/resources/db/collection/schema.sql diff --git a/mybatis-plus-join-annotation/pom.xml b/mybatis-plus-join-annotation/pom.xml index d662729..463b4c9 100644 --- a/mybatis-plus-join-annotation/pom.xml +++ b/mybatis-plus-join-annotation/pom.xml @@ -1,4 +1,5 @@ + @@ -8,6 +9,7 @@ mybatis-plus-join-root 2.0.0 + 2.0.0 mybatis-plus-join-annotation mybatis-plus-join-annotation diff --git a/mybatis-plus-join-boot-starter/pom.xml b/mybatis-plus-join-boot-starter/pom.xml index a5eb38b..660091f 100644 --- a/mybatis-plus-join-boot-starter/pom.xml +++ b/mybatis-plus-join-boot-starter/pom.xml @@ -1,4 +1,5 @@ + @@ -8,6 +9,7 @@ mybatis-plus-join-root 2.0.0 + 2.0.0 mybatis-plus-join-boot-starter mybatis-plus-join-boot-starter @@ -45,7 +47,7 @@ com.github.yulichang mybatis-plus-join-core - ${mybaits-plus-join.version} + 2.0.0 org.springframework.boot diff --git a/mybatis-plus-join-core/pom.xml b/mybatis-plus-join-core/pom.xml index d202a4e..d48f1c6 100644 --- a/mybatis-plus-join-core/pom.xml +++ b/mybatis-plus-join-core/pom.xml @@ -9,6 +9,7 @@ mybatis-plus-join-root 2.0.0 + 2.0.0 mybatis-plus-join-core mybatis-plus-join-core @@ -46,7 +47,7 @@ com.github.yulichang mybatis-plus-join-annotation - ${mybaits-plus-join.version} + 2.0.0 com.baomidou @@ -60,6 +61,12 @@ ${lombok.version} provided + + org.slf4j + slf4j-api + provided + 2.0.3 + org.springframework spring-aop diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java index f26c341..5e1d268 100644 --- a/mybatis-plus-join-core/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java @@ -7,7 +7,6 @@ import com.baomidou.mybatisplus.core.toolkit.*; import com.github.yulichang.interfaces.MPJBaseJoin; import com.github.yulichang.method.MPJResultType; import com.github.yulichang.toolkit.Constant; -import com.github.yulichang.toolkit.ReflectionKit; import com.github.yulichang.toolkit.support.SelectColumn; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.github.yulichang.wrapper.resultmap.MybatisLabel; @@ -150,7 +149,6 @@ public class MPJInterceptor implements Interceptor { TableInfo tableInfo = TableInfoHelper.getTableInfo(resultType); String id = ms.getId() + StringPool.DOT + Constants.MYBATIS_PLUS + StringPool.UNDERSCORE + resultType.getName(); if (!(obj instanceof MPJLambdaWrapper) || Map.class.isAssignableFrom(resultType) || - ReflectionKit.isPrimitiveOrWrapper(resultType) || Collection.class.isAssignableFrom(resultType)) { result.add(getDefaultResultMap(tableInfo, ms, resultType, id)); return result; @@ -209,56 +207,86 @@ public class MPJInterceptor implements Interceptor { //移除result中不存在的标签 resultMappings.removeIf(i -> !fieldMap.containsKey(i.getProperty())); if (wrapper.isResultMap()) { - buildResult(ms, wrapper.getResultMapMybatisLabel(), columnSet, resultMappings, columnList); + for (Object o : wrapper.getResultMapMybatisLabel()) { + MybatisLabel label = (MybatisLabel) o; + resultMappings.add(buildResult(ms, label, columnSet, columnList)); + } } result.add(new ResultMap.Builder(ms.getConfiguration(), id, resultType, resultMappings).build()); return result; } - private void buildResult(MappedStatement ms, List> mybatisLabel, Set columnSet, - List parentMappings, List columnList) { - for (MybatisLabel mpjColl : mybatisLabel) { - List list = mpjColl.getResultList(); - if (CollectionUtils.isEmpty(list)) { - continue; + + //fix 重上往下会有resultMap覆盖问题,应该从根节点开始,id向上传递 + + /** + * @return 返回节点id + */ + private ResultMapping buildResult(MappedStatement ms, MybatisLabel mybatisLabel, Set columnSet, + List columnList) { + List resultList = mybatisLabel.getResultList(); + if (CollectionUtils.isEmpty(resultList)) { + return null; + } + List childMapping = new ArrayList<>(resultList.size()); + for (Result r : resultList) { + String columnName = r.getColumn(); + //列名去重 + columnName = getColumn(columnSet, columnName); + columnList.add(SelectColumn.of(mybatisLabel.getEntityClass(), r.getColumn(), null, + Objects.equals(columnName, r.getColumn()) ? null : columnName, null, null, true, null)); + ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), r.getProperty(), + StringUtils.getTargetColumn(columnName), r.getJavaType()); + if (r.isId()) {//主键标记为id标签 + builder.flags(Collections.singletonList(ResultFlag.ID)); } - List childMapping = new ArrayList<>(list.size()); - for (Result r : list) { - String columnName = r.getColumn(); - //列名去重 - columnName = getColumn(columnSet, columnName); - columnList.add(SelectColumn.of(mpjColl.getEntityClass(), r.getColumn(), null, - Objects.equals(columnName, r.getColumn()) ? null : columnName, null, null, true, null)); - ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), r.getProperty(), - StringUtils.getTargetColumn(columnName), r.getJavaType()); - if (r.isId()) {//主键标记为id标签 - builder.flags(Collections.singletonList(ResultFlag.ID)); - } - //TypeHandle - TableFieldInfo info = r.getTableFieldInfo(); - if (info != null && info.getTypeHandler() != null && info.getTypeHandler() != UnknownTypeHandler.class) { - builder.typeHandler(getTypeHandler(ms, info)); - } - childMapping.add(builder.build()); + //TypeHandle + TableFieldInfo info = r.getTableFieldInfo(); + if (info != null && info.getTypeHandler() != null && info.getTypeHandler() != UnknownTypeHandler.class) { + builder.typeHandler(getTypeHandler(ms, info)); } - //嵌套处理 - if (CollectionUtils.isNotEmpty(mpjColl.getMybatisLabels())) { - this.buildResult(ms, mpjColl.getMybatisLabels(), columnSet, childMapping, columnList); - } - String childId = "MPJ_" + mpjColl.getEntityClass().getName() + StringPool.UNDERSCORE + mpjColl.getOfType().getName() + + childMapping.add(builder.build()); + } + + String childId; + if (CollectionUtils.isEmpty(mybatisLabel.getMybatisLabels())) { + childId = "MPJ_" + mybatisLabel.getEntityClass().getName() + StringPool.UNDERSCORE + mybatisLabel.getOfType().getName() + StringPool.UNDERSCORE + childMapping.stream().map(i -> "(" + (CollectionUtils.isEmpty(i.getFlags()) ? ResultFlag.CONSTRUCTOR : i.getFlags().get(0)) + "-" + i.getProperty() + "-" + i.getColumn() + ")") .collect(Collectors.joining(StringPool.DASH)); - parentMappings.add(new ResultMapping.Builder(ms.getConfiguration(), mpjColl.getProperty()) - .javaType(mpjColl.getJavaType()) - .nestedResultMapId(childId) - .build()); - //双检 - if (!ms.getConfiguration().getResultMapNames().contains(childId)) { - ResultMap build = new ResultMap.Builder(ms.getConfiguration(), childId, mpjColl.getOfType(), childMapping).build(); - MPJInterceptor.addResultMap(ms, childId, build); + } else { + //递归调用 + StringBuilder sb = new StringBuilder("MPJ_["); + for (MybatisLabel o : mybatisLabel.getMybatisLabels()) { + if (Objects.isNull(o)) { + continue; + } + ResultMapping result = buildResult(ms, o, columnSet, columnList); + if (Objects.isNull(result)) { + continue; + } + childMapping.add(result); + sb.append(result.getNestedResultMapId()); + sb.append("]"); } + sb.append("_MPJ_") + .append(mybatisLabel.getEntityClass().getName()) + .append(StringPool.UNDERSCORE) + .append(mybatisLabel.getOfType().getName()) + .append(StringPool.UNDERSCORE); + childId = sb + childMapping.stream().map(i -> "(" + (CollectionUtils.isEmpty(i.getFlags()) ? + ResultFlag.CONSTRUCTOR : i.getFlags().get(0)) + "-" + i.getProperty() + "-" + i.getColumn() + ")") + .collect(Collectors.joining(StringPool.DASH)); } + //双检 + if (!ms.getConfiguration().getResultMapNames().contains(childId)) { + ResultMap build = new ResultMap.Builder(ms.getConfiguration(), childId, mybatisLabel.getOfType(), childMapping).build(); + MPJInterceptor.addResultMap(ms, childId, build); + } + return new ResultMapping.Builder(ms.getConfiguration(), mybatisLabel.getProperty()) + .javaType(mybatisLabel.getJavaType()) + .nestedResultMapId(childId) + .build(); } /** diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/ClassUtils.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/ClassUtils.java new file mode 100644 index 0000000..71f6cd0 --- /dev/null +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/ClassUtils.java @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2011-2022, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.yulichang.toolkit; + +import com.baomidou.mybatisplus.core.toolkit.Assert; +import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils; +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import org.apache.ibatis.io.Resources; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.List; + +/** + *

+ * ClassUtils + *

+ * + * @author Caratacus + * @author HCL + * @since 2017/07/08 + */ +@SuppressWarnings("All") +public final class ClassUtils { + + private static ClassLoader systemClassLoader; + + static { + try { + systemClassLoader = ClassLoader.getSystemClassLoader(); + } catch (SecurityException ignored) { + // AccessControlException on Google App Engine + } + } + + /** + * 代理 class 的名称 + */ + private static final List PROXY_CLASS_NAMES = Arrays.asList("net.sf.cglib.proxy.Factory" + // cglib + , "org.springframework.cglib.proxy.Factory" + , "javassist.util.proxy.ProxyObject" + // javassist + , "org.apache.ibatis.javassist.util.proxy.ProxyObject"); + + private ClassUtils() { + } + + /** + * 判断传入的类型是否是布尔类型 + * + * @param type 类型 + * @return 如果是原生布尔或者包装类型布尔,均返回 true + */ + public static boolean isBoolean(Class type) { + return type == boolean.class || Boolean.class == type; + } + + /** + * 判断是否为代理对象 + * + * @param clazz 传入 class 对象 + * @return 如果对象class是代理 class,返回 true + */ + public static boolean isProxy(Class clazz) { + if (clazz != null) { + for (Class cls : clazz.getInterfaces()) { + if (PROXY_CLASS_NAMES.contains(cls.getName())) { + return true; + } + } + } + return false; + } + + /** + *

+ * 获取当前对象的 class + *

+ * + * @param clazz 传入 + * @return 如果是代理的class,返回父 class,否则返回自身 + */ + public static Class getUserClass(Class clazz) { + Assert.notNull(clazz, "Class must not be null"); + return isProxy(clazz) ? clazz.getSuperclass() : clazz; + } + + /** + *

+ * 获取当前对象的class + *

+ * + * @param object 对象 + * @return 返回对象的 user class + */ + public static Class getUserClass(Object object) { + Assert.notNull(object, "Instance must not be null"); + return getUserClass(object.getClass()); + } + + /** + *

+ * 根据指定的 class , 实例化一个对象,根据构造参数来实例化 + *

+ *

+ * 在 java9 及其之后的版本 Class.newInstance() 方法已被废弃 + *

+ * + * @param clazz 需要实例化的对象 + * @param 类型,由输入类型决定 + * @return 返回新的实例 + */ + public static T newInstance(Class clazz) { + try { + Constructor constructor = clazz.getDeclaredConstructor(); + constructor.setAccessible(true); + return constructor.newInstance(); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | + NoSuchMethodException e) { + throw ExceptionUtils.mpe("实例化对象时出现错误,请尝试给 %s 添加无参的构造方法", e, clazz.getName()); + } + } + + /** + * 实例化对象. + * + * @param clazzName 类名 + * @param 类型 + * @return 实例 + * @since 3.3.2 + */ + @SuppressWarnings("unchecked") + public static T newInstance(String clazzName) { + return (T) newInstance(toClassConfident(clazzName)); + } + + + /** + *

+ * 请仅在确定类存在的情况下调用该方法 + *

+ * + * @param name 类名称 + * @return 返回转换后的 Class + */ + public static Class toClassConfident(String name) { + return toClassConfident(name, null); + } + + /** + * @param name + * @param classLoader + * @return + * @since 3.4.3 + */ + public static Class toClassConfident(String name, ClassLoader classLoader) { + try { + return loadClass(name, getClassLoaders(classLoader)); + } catch (ClassNotFoundException e) { + throw ExceptionUtils.mpe("找不到指定的class!请仅在明确确定会有 class 的时候,调用该方法", e); + } + } + + private static Class loadClass(String className, ClassLoader[] classLoaders) throws ClassNotFoundException { + for (ClassLoader classLoader : classLoaders) { + if (classLoader != null) { + try { + return Class.forName(className, true, classLoader); + } catch (ClassNotFoundException e) { + // ignore + } + } + } + throw new ClassNotFoundException("Cannot find class: " + className); + } + + + /** + * Determine the name of the package of the given class, + * e.g. "java.lang" for the {@code java.lang.String} class. + * + * @param clazz the class + * @return the package name, or the empty String if the class + * is defined in the default package + */ + public static String getPackageName(Class clazz) { + Assert.notNull(clazz, "Class must not be null"); + return getPackageName(clazz.getName()); + } + + /** + * Determine the name of the package of the given fully-qualified class name, + * e.g. "java.lang" for the {@code java.lang.String} class name. + * + * @param fqClassName the fully-qualified class name + * @return the package name, or the empty String if the class + * is defined in the default package + */ + public static String getPackageName(String fqClassName) { + Assert.notNull(fqClassName, "Class name must not be null"); + int lastDotIndex = fqClassName.lastIndexOf(StringPool.DOT); + return (lastDotIndex != -1 ? fqClassName.substring(0, lastDotIndex) : StringPool.EMPTY); + } + + /** + * Return the default ClassLoader to use: typically the thread context + * ClassLoader, if available; the ClassLoader that loaded the ClassUtils + * class will be used as fallback. + *

Call this method if you intend to use the thread context ClassLoader + * in a scenario where you clearly prefer a non-null ClassLoader reference: + * for example, for class path resource loading (but not necessarily for + * {@code Class.forName}, which accepts a {@code null} ClassLoader + * reference as well). + * + * @return the default ClassLoader (only {@code null} if even the system + * ClassLoader isn't accessible) + * @see Thread#getContextClassLoader() + * @see ClassLoader#getSystemClassLoader() + * @since 3.3.2 + */ + @Deprecated + public static ClassLoader getDefaultClassLoader() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (Throwable ex) { + // Cannot access thread context ClassLoader - falling back... + } + if (cl == null) { + // No thread context class loader -> use class loader of this class. + cl = ClassUtils.class.getClassLoader(); + if (cl == null) { + // getClassLoader() returning null indicates the bootstrap ClassLoader + try { + cl = ClassLoader.getSystemClassLoader(); + } catch (Throwable ex) { + // Cannot access system ClassLoader - oh well, maybe the caller can live with null... + } + } + } + return cl; + } + + private static ClassLoader[] getClassLoaders(ClassLoader classLoader) { + return new ClassLoader[]{ + classLoader, + Resources.getDefaultClassLoader(), + Thread.currentThread().getContextClassLoader(), + ClassUtils.class.getClassLoader(), + systemClassLoader}; + } +} diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/InterceptorList.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/InterceptorList.java index e8620cc..c113632 100644 --- a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/InterceptorList.java +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/InterceptorList.java @@ -13,7 +13,7 @@ import java.util.function.Predicate; * 保证 MPJInterceptor 再最后一个(第一个执行) * * @author yulichang - * @since 1.2.5 + * @since 1.3.0 */ public class InterceptorList extends ArrayList { diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java index e782640..9e782cd 100644 --- a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java @@ -5,13 +5,13 @@ 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.support.SFunction; -import com.github.yulichang.toolkit.support.ColumnCache; -import com.github.yulichang.toolkit.support.SerializedLambda; +import com.github.yulichang.toolkit.support.*; import org.apache.ibatis.reflection.property.PropertyNamer; -import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.util.Map; -import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import static java.util.Locale.ENGLISH; @@ -19,50 +19,54 @@ import static java.util.Locale.ENGLISH; /** * copy {@link com.baomidou.mybatisplus.core.toolkit.LambdaUtils} */ +@SuppressWarnings("unused") public final class LambdaUtils { /* ******* 自定义方法 *********** */ public static String getName(SFunction fn) { - return PropertyNamer.methodToProperty(resolve(fn).getImplMethodName()); + LambdaMeta extract = extract(fn); + String name = PropertyNamer.methodToProperty(extract.getImplMethodName()); + if (Character.isUpperCase(name.charAt(0))) { + Map map = MPJReflectionKit.getFieldMap(extract.getInstantiatedClass()); + if (map.containsKey(name)) { + return name; + } else { + return map.keySet().stream().filter(i -> i.equalsIgnoreCase(name)).findFirst().orElse(null); + } + } + return name; } @SuppressWarnings("unchecked") public static Class getEntityClass(SFunction fn) { - return (Class) resolve(fn).getInstantiatedType(); + return (Class) extract(fn).getInstantiatedClass(); } /* ******* 自定义方法 结束 以下代码均为拷贝 *********** */ - /** - * 字段映射 - */ private static final Map> COLUMN_CACHE_MAP = new ConcurrentHashMap<>(); /** - * SerializedLambda 反序列化缓存 - */ - private static final Map> FUNC_CACHE = new ConcurrentHashMap<>(); - - /** - * 解析 lambda 表达式, 该方法只是调用了 {@link SerializedLambda#resolve(SFunction)} 中的方法,在此基础上加了缓存。 * 该缓存可能会在任意不定的时间被清除 * * @param func 需要解析的 lambda 对象 * @param 类型,被调用的 Function 对象的目标类型 * @return 返回解析后的结果 - * @see SerializedLambda#resolve(SFunction) */ - public static SerializedLambda resolve(SFunction func) { - Class clazz = func.getClass(); - String name = clazz.getName(); - return Optional.ofNullable(FUNC_CACHE.get(name)) - .map(WeakReference::get) - .orElseGet(() -> { - SerializedLambda lambda = SerializedLambda.resolve(func); - FUNC_CACHE.put(name, new WeakReference<>(lambda)); - return lambda; - }); + public static LambdaMeta extract(SFunction func) { + // 1. IDEA 调试模式下 lambda 表达式是一个代理 + if (func instanceof Proxy) { + return new IdeaProxyLambdaMeta((Proxy) func); + } + // 2. 反射读取 + try { + Method method = func.getClass().getDeclaredMethod("writeReplace"); + return new ReflectLambdaMeta((java.lang.invoke.SerializedLambda) ReflectionKit.setAccessible(method).invoke(func)); + } catch (Throwable e) { + // 3. 反射失败使用序列化的方式读取 + return new ShadowLambdaMeta(SerializedLambda.extract(func)); + } } /** @@ -79,6 +83,14 @@ public final class LambdaUtils { return key.toUpperCase(ENGLISH); } + /** + * 将传入的表信息加入缓存 + * + * @param tableInfo 表信息 + */ + public static void installCache(TableInfo tableInfo) { + COLUMN_CACHE_MAP.put(tableInfo.getEntityType().getName(), createColumnCacheMap(tableInfo)); + } /** * 缓存实体字段 MAP 信息 @@ -115,5 +127,4 @@ public final class LambdaUtils { return info == null ? null : createColumnCacheMap(info); }); } - } diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/MPJReflectionKit.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/MPJReflectionKit.java new file mode 100644 index 0000000..23f3d14 --- /dev/null +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/MPJReflectionKit.java @@ -0,0 +1,61 @@ +package com.github.yulichang.toolkit; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 反射工具类 + * + * @author yulichang + * @since 2.0.0 + */ +@SuppressWarnings("unused") +public final class MPJReflectionKit { + + private static final Map, Map> CLASS_FIELD_CACHE = new ConcurrentHashMap<>(); + + + /** + * Collection字段的泛型 + */ + public static Class getGenericType(Field field) { + Type type = field.getGenericType(); + //没有写泛型 + if (!(type instanceof ParameterizedType)) { + return Object.class; + } + ParameterizedType pt = (ParameterizedType) type; + Type[] actualTypeArguments = pt.getActualTypeArguments(); + Type argument = actualTypeArguments[0]; + //通配符泛型 ? , ? extends XXX , ? super XXX + if (argument instanceof WildcardType) { + //获取上界 + Type[] types = ((WildcardType) argument).getUpperBounds(); + return (Class) types[0]; + } + return (Class) argument; + } + + /** + * 获取该类的所有属性列表 + * + * @param clazz 反射类 + */ + public static Map getFieldMap(Class clazz) { + if (clazz == null) { + return new HashMap<>(); + } + Map fieldMap = CLASS_FIELD_CACHE.get(clazz); + if (fieldMap != null) { + return fieldMap; + } + Map map = ReflectionKit.getFieldMap(clazz); + CLASS_FIELD_CACHE.put(clazz, map); + return map; + } +} diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java index c681018..d9d92a8 100644 --- a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2021, baomidou (jobob@qq.com). + * Copyright (c) 2011-2022, baomidou (jobob@qq.com). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,15 +15,16 @@ */ package com.github.yulichang.toolkit; -import com.baomidou.mybatisplus.core.toolkit.Assert; -import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; -import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils; -import org.apache.ibatis.logging.Log; -import org.apache.ibatis.logging.LogFactory; +import com.baomidou.mybatisplus.core.toolkit.*; +import com.baomidou.mybatisplus.core.toolkit.reflect.GenericTypeUtils; -import java.lang.reflect.*; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.security.AccessController; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -37,14 +38,14 @@ import static java.util.stream.Collectors.toMap; * @author hcl * @since 2016-09-22 */ -@SuppressWarnings("unused") +@SuppressWarnings("All") public final class ReflectionKit { - private static final Log logger = LogFactory.getLog(ReflectionKit.class); /** * class field cache */ private static final Map, List> CLASS_FIELD_CACHE = new ConcurrentHashMap<>(); + @Deprecated private static final Map, Class> PRIMITIVE_WRAPPER_TYPE_MAP = new IdentityHashMap<>(8); private static final Map, Class> PRIMITIVE_TYPE_TO_WRAPPER_MAP = new IdentityHashMap<>(8); @@ -83,26 +84,20 @@ public final class ReflectionKit { } } - /** - * Collection字段的泛型 + *

+ * 反射对象获取泛型 + *

+ * + * @param clazz 对象 + * @param genericIfc 所属泛型父类 + * @param index 泛型所在位置 + * @return Class */ - public static Class getGenericType(Field field) { - Type type = field.getGenericType(); - //没有写泛型 - if (!(type instanceof ParameterizedType)) { - return Object.class; - } - ParameterizedType pt = (ParameterizedType) type; - Type[] actualTypeArguments = pt.getActualTypeArguments(); - Type argument = actualTypeArguments[0]; - //通配符泛型 ? , ? extends XXX , ? super XXX - if (argument instanceof WildcardType) { - //获取上界 - Type[] types = ((WildcardType) argument).getUpperBounds(); - return (Class) types[0]; - } - return (Class) argument; + public static Class getSuperClassGenericType(final Class clazz, final Class genericIfc, final int index) { + //update by noear @2021-09-03 + Class[] typeArguments = GenericTypeUtils.resolveTypeArguments(ClassUtils.getUserClass(clazz), genericIfc); + return null == typeArguments ? null : typeArguments[index]; } /** @@ -114,7 +109,7 @@ public final class ReflectionKit { */ public static Map getFieldMap(Class clazz) { List fieldList = getFieldList(clazz); - return CollectionUtils.isNotEmpty(fieldList) ? fieldList.stream().collect(Collectors.toMap(Field::getName, field -> field)) : Collections.emptyMap(); + return CollectionUtils.isNotEmpty(fieldList) ? fieldList.stream().collect(Collectors.toMap(Field::getName, Function.identity())) : Collections.emptyMap(); } /** @@ -145,11 +140,11 @@ public final class ReflectionKit { * 中间表实体重写父类属性 ` private transient Date createTime; ` */ return fieldMap.values().stream() - /* 过滤静态属性 */ - .filter(f -> !Modifier.isStatic(f.getModifiers())) - /* 过滤 transient关键字修饰的属性 */ - .filter(f -> !Modifier.isTransient(f.getModifiers())) - .collect(Collectors.toList()); + /* 过滤静态属性 */ + .filter(f -> !Modifier.isStatic(f.getModifiers())) + /* 过滤 transient关键字修饰的属性 */ + .filter(f -> !Modifier.isTransient(f.getModifiers())) + .collect(Collectors.toList()); }); } @@ -164,12 +159,12 @@ public final class ReflectionKit { public static Map excludeOverrideSuperField(Field[] fields, List superFieldList) { // 子类属性 Map fieldMap = Stream.of(fields).collect(toMap(Field::getName, identity(), - (u, v) -> { - throw new IllegalStateException(String.format("Duplicate key %s", u)); - }, - LinkedHashMap::new)); + (u, v) -> { + throw new IllegalStateException(String.format("Duplicate key %s", u)); + }, + LinkedHashMap::new)); superFieldList.stream().filter(field -> !fieldMap.containsKey(field.getName())) - .forEach(f -> fieldMap.put(f.getName(), f)); + .forEach(f -> fieldMap.put(f.getName(), f)); return fieldMap; } @@ -179,6 +174,7 @@ public final class ReflectionKit { * @param clazz class * @return 是否基本类型或基本包装类型 */ + @Deprecated public static boolean isPrimitiveOrWrapper(Class clazz) { Assert.notNull(clazz, "Class must not be null"); return (clazz.isPrimitive() || PRIMITIVE_WRAPPER_TYPE_MAP.containsKey(clazz)); @@ -187,4 +183,16 @@ public final class ReflectionKit { public static Class resolvePrimitiveIfNecessary(Class clazz) { return (clazz.isPrimitive() && clazz != void.class ? PRIMITIVE_TYPE_TO_WRAPPER_MAP.get(clazz) : clazz); } + + /** + * 设置可访问对象的可访问权限为 true + * + * @param object 可访问的对象 + * @param 类型 + * @return 返回设置后的对象 + */ + public static T setAccessible(T object) { + return AccessController.doPrivileged(new SetAccessibleAction<>(object)); + } + } diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java index 2d4df23..9a4c95c 100644 --- a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java @@ -8,7 +8,7 @@ import lombok.Getter; * * @author yulichang * @see com.baomidou.mybatisplus.core.toolkit.support.ColumnCache - * @since 1.2.5 + * @since 1.3.0 */ public class ColumnCache extends com.baomidou.mybatisplus.core.toolkit.support.ColumnCache { diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/IdeaProxyLambdaMeta.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/IdeaProxyLambdaMeta.java new file mode 100644 index 0000000..a4c3482 --- /dev/null +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/IdeaProxyLambdaMeta.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011-2022, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.yulichang.toolkit.support; + +import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; +import com.baomidou.mybatisplus.core.toolkit.ReflectionKit; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; + +/** + * 在 IDEA 的 Evaluate 中执行的 Lambda 表达式元数据需要使用该类处理元数据 + *

+ * Create by hcl at 2021/5/17 + */ +public class IdeaProxyLambdaMeta implements LambdaMeta { + private static final Field FIELD_MEMBER_NAME; + private static final Field FIELD_MEMBER_NAME_CLAZZ; + private static final Field FIELD_MEMBER_NAME_NAME; + + static { + try { + Class classDirectMethodHandle = Class.forName("java.lang.invoke.DirectMethodHandle"); + FIELD_MEMBER_NAME = ReflectionKit.setAccessible(classDirectMethodHandle.getDeclaredField("member")); + Class classMemberName = Class.forName("java.lang.invoke.MemberName"); + FIELD_MEMBER_NAME_CLAZZ = ReflectionKit.setAccessible(classMemberName.getDeclaredField("clazz")); + FIELD_MEMBER_NAME_NAME = ReflectionKit.setAccessible(classMemberName.getDeclaredField("name")); + } catch (ClassNotFoundException | NoSuchFieldException e) { + throw new MybatisPlusException(e); + } + } + + private final Class clazz; + private final String name; + + public IdeaProxyLambdaMeta(Proxy func) { + InvocationHandler handler = Proxy.getInvocationHandler(func); + try { + Object dmh = ReflectionKit.setAccessible(handler.getClass().getDeclaredField("val$target")).get(handler); + Object member = FIELD_MEMBER_NAME.get(dmh); + clazz = (Class) FIELD_MEMBER_NAME_CLAZZ.get(member); + name = (String) FIELD_MEMBER_NAME_NAME.get(member); + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new MybatisPlusException(e); + } + } + + @Override + public String getImplMethodName() { + return name; + } + + @Override + public Class getInstantiatedClass() { + return clazz; + } + + @Override + public String toString() { + return clazz.getSimpleName() + "::" + name; + } + +} diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/LambdaMeta.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/LambdaMeta.java new file mode 100644 index 0000000..80295f7 --- /dev/null +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/LambdaMeta.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011-2022, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.yulichang.toolkit.support; + +/** + * Lambda 信息 + *

+ * Created by hcl at 2021/5/14 + */ +public interface LambdaMeta { + + /** + * 获取 lambda 表达式实现方法的名称 + * + * @return lambda 表达式对应的实现方法名称 + */ + String getImplMethodName(); + + /** + * 实例化该方法的类 + * + * @return 返回对应的类名称 + */ + Class getInstantiatedClass(); + +} diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ReflectLambdaMeta.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ReflectLambdaMeta.java new file mode 100644 index 0000000..11796f7 --- /dev/null +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ReflectLambdaMeta.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2011-2022, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.yulichang.toolkit.support; + + +import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.github.yulichang.toolkit.ClassUtils; +import com.github.yulichang.toolkit.ReflectionKit; +import lombok.extern.slf4j.Slf4j; + +import java.lang.invoke.SerializedLambda; +import java.lang.reflect.Field; + +/** + * Created by hcl at 2021/5/14 + */ +@Slf4j +public class ReflectLambdaMeta implements LambdaMeta { + private static final Field FIELD_CAPTURING_CLASS; + + static { + Field fieldCapturingClass; + try { + Class aClass = SerializedLambda.class; + fieldCapturingClass = ReflectionKit.setAccessible(aClass.getDeclaredField("capturingClass")); + } catch (Throwable e) { + // 解决高版本 jdk 的问题 gitee: https://gitee.com/baomidou/mybatis-plus/issues/I4A7I5 + log.warn(e.getMessage()); + fieldCapturingClass = null; + } + FIELD_CAPTURING_CLASS = fieldCapturingClass; + } + + private final SerializedLambda lambda; + + public ReflectLambdaMeta(SerializedLambda lambda) { + this.lambda = lambda; + } + + @Override + public String getImplMethodName() { + return lambda.getImplMethodName(); + } + + @Override + public Class getInstantiatedClass() { + String instantiatedMethodType = lambda.getInstantiatedMethodType(); + String instantiatedType = instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(StringPool.SEMICOLON)).replace(StringPool.SLASH, StringPool.DOT); + return ClassUtils.toClassConfident(instantiatedType, getCapturingClassClassLoader()); + } + + private ClassLoader getCapturingClassClassLoader() { + // 如果反射失败,使用默认的 classloader + if (FIELD_CAPTURING_CLASS == null) { + return null; + } + try { + return ((Class) FIELD_CAPTURING_CLASS.get(lambda)).getClassLoader(); + } catch (IllegalAccessException e) { + throw new MybatisPlusException(e); + } + } + +} diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SelectColumn.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SelectColumn.java index 1d4d96c..964cfc1 100644 --- a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SelectColumn.java +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SelectColumn.java @@ -9,7 +9,7 @@ import lombok.Getter; * MPJLambdaWrapper 查询字段 * * @author yulichang - * @since 1.2.5 + * @since 1.3.0 */ @Getter public class SelectColumn { diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SerializedLambda.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SerializedLambda.java index c1d5195..4b7d4cb 100644 --- a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SerializedLambda.java +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SerializedLambda.java @@ -1,18 +1,31 @@ +/* + * Copyright (c) 2011-2022, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.github.yulichang.toolkit.support; -import com.baomidou.mybatisplus.core.toolkit.ClassUtils; -import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils; -import com.baomidou.mybatisplus.core.toolkit.SerializationUtils; -import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; import java.io.*; /** - * copy mp before 3.4.3 + * 当前类是 {@link java.lang.invoke.SerializedLambda } 的一个镜像 + *

+ * Create by hcl at 2020/7/17 */ -@SuppressWarnings("unused") +@SuppressWarnings("ALL") public class SerializedLambda implements Serializable { - private static final long serialVersionUID = 8025925345765570181L; private Class capturingClass; @@ -26,98 +39,35 @@ public class SerializedLambda implements Serializable { private String instantiatedMethodType; private Object[] capturedArgs; - /** - * 通过反序列化转换 lambda 表达式,该方法只能序列化 lambda 表达式,不能序列化接口实现或者正常非 lambda 写法的对象 - * - * @param lambda lambda对象 - * @return 返回解析后的 SerializedLambda - */ - public static SerializedLambda resolve(SFunction lambda) { - if (!lambda.getClass().isSynthetic()) { - throw ExceptionUtils.mpe("该方法仅能传入 lambda 表达式产生的合成类"); - } - try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(SerializationUtils.serialize(lambda))) { - @Override - protected Class resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException { - Class clazz; - try { - clazz = ClassUtils.toClassConfident(objectStreamClass.getName()); - } catch (Exception ex) { - clazz = super.resolveClass(objectStreamClass); + public static SerializedLambda extract(Serializable serializable) { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos)) { + oos.writeObject(serializable); + oos.flush(); + try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())) { + @Override + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + Class clazz = super.resolveClass(desc); + return clazz == java.lang.invoke.SerializedLambda.class ? SerializedLambda.class : clazz; } - return clazz == java.lang.invoke.SerializedLambda.class ? SerializedLambda.class : clazz; + + }) { + return (SerializedLambda) ois.readObject(); } - }) { - return (SerializedLambda) objIn.readObject(); - } catch (ClassNotFoundException | IOException e) { - throw ExceptionUtils.mpe("This is impossible to happen", e); + } catch (IOException | ClassNotFoundException e) { + throw new MybatisPlusException(e); } } - /** - * 获取接口 class - * - * @return 返回 class 名称 - */ - public String getFunctionalInterfaceClassName() { - return normalizedName(functionalInterfaceClass); + public String getInstantiatedMethodType() { + return instantiatedMethodType; } - /** - * 获取实现的 class - * - * @return 实现类 - */ - public Class getImplClass() { - return ClassUtils.toClassConfident(getImplClassName()); + public Class getCapturingClass() { + return capturingClass; } - /** - * 获取 class 的名称 - * - * @return 类名 - */ - public String getImplClassName() { - return normalizedName(implClass); - } - - /** - * 获取实现者的方法名称 - * - * @return 方法名称 - */ public String getImplMethodName() { return implMethodName; } - - /** - * 正常化类名称,将类名称中的 / 替换为 . - * - * @param name 名称 - * @return 正常的类名 - */ - private String normalizedName(String name) { - return name.replace('/', '.'); - } - - /** - * @return 获取实例化方法的类型 - */ - public Class getInstantiatedType() { - String instantiatedTypeName = normalizedName(instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(';'))); - return ClassUtils.toClassConfident(instantiatedTypeName); - } - - /** - * @return 字符串形式 - */ - @Override - public String toString() { - String interfaceName = getFunctionalInterfaceClassName(); - String implName = getImplClassName(); - return String.format("%s -> %s::%s", - interfaceName.substring(interfaceName.lastIndexOf('.') + 1), - implName.substring(implName.lastIndexOf('.') + 1), - implMethodName); - } } diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ShadowLambdaMeta.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ShadowLambdaMeta.java new file mode 100644 index 0000000..d1a3ad4 --- /dev/null +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ShadowLambdaMeta.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011-2022, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.yulichang.toolkit.support; + + +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.github.yulichang.toolkit.ClassUtils; + +/** + * 基于 {@link com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda} 创建的元信息 + *

+ * Create by hcl at 2021/7/7 + */ +public class ShadowLambdaMeta implements LambdaMeta { + private final SerializedLambda lambda; + + public ShadowLambdaMeta(SerializedLambda lambda) { + this.lambda = lambda; + } + + @Override + public String getImplMethodName() { + return lambda.getImplMethodName(); + } + + @Override + public Class getInstantiatedClass() { + String instantiatedMethodType = lambda.getInstantiatedMethodType(); + String instantiatedType = instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(StringPool.SEMICOLON)).replace(StringPool.SLASH, StringPool.DOT); + return ClassUtils.toClassConfident(instantiatedType, lambda.getCapturingClass().getClassLoader()); + } + +} diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/MPJLambdaWrapper.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/MPJLambdaWrapper.java index bbadbb7..51e47cf 100644 --- a/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/MPJLambdaWrapper.java +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/MPJLambdaWrapper.java @@ -10,11 +10,7 @@ import com.baomidou.mybatisplus.core.toolkit.Assert; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; -import com.github.yulichang.exception.MPJException; -import com.github.yulichang.toolkit.Constant; -import com.github.yulichang.toolkit.LambdaUtils; -import com.github.yulichang.toolkit.MPJWrappers; -import com.github.yulichang.toolkit.ReflectionKit; +import com.github.yulichang.toolkit.*; import com.github.yulichang.toolkit.support.ColumnCache; import com.github.yulichang.toolkit.support.SelectColumn; import com.github.yulichang.wrapper.enums.BaseFuncEnum; @@ -165,7 +161,7 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper * 会自动将 UserAddressDO类中相同属性的字段 以mybatis的方式映射到UserDTO.addressListDTO属性中 * - * @since 1.2.5 + * @since 1.3.0 * * @param child 连表数据库实体类 * @param dtoField 包装类对应的属性 @@ -177,19 +173,16 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper> MPJLambdaWrapper selectCollection(Class child, SFunction dtoField) { String dtoFieldName = LambdaUtils.getName(dtoField); Class dtoClass = LambdaUtils.getEntityClass(dtoField); - Map fieldMap = ReflectionKit.getFieldMap(dtoClass); + Map fieldMap = MPJReflectionKit.getFieldMap(dtoClass); Field field = fieldMap.get(dtoFieldName); this.resultMap = true; - Class genericType = ReflectionKit.getGenericType(field); + Class genericType = MPJReflectionKit.getGenericType(field); MybatisLabel.Builder builder; if (genericType == null || genericType.isAssignableFrom(child)) { //找不到集合泛型 List List List , 直接查询数据库实体 builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType()); } else { Class ofType = (Class) genericType; - if (ReflectionKit.isPrimitiveOrWrapper(ofType)) { - throw new MPJException("collection 不支持基本数据类型"); - } builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), ofType, true); } this.resultMapMybatisLabel.add(builder.build()); @@ -214,7 +207,7 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper的方式映射到UserDTO.addressListDTO属性中 * - * @since 1.2.5 + * @since 1.3.0 * * @param child 连表数据库实体类 * @param dtoField 包装类对应的属性 @@ -228,10 +221,10 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper child, SFunction dtoField, MFunc> collection) { String dtoFieldName = LambdaUtils.getName(dtoField); Class dtoClass = LambdaUtils.getEntityClass(dtoField); - Field field = ReflectionKit.getFieldMap(dtoClass).get(dtoFieldName); + Field field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName); this.resultMap = true; //获取集合泛型 - Class genericType = ReflectionKit.getGenericType(field); + Class genericType = MPJReflectionKit.getGenericType(field); Class ofType = (Class) genericType; MybatisLabel.Builder builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), ofType, false); this.resultMapMybatisLabel.add(collection.apply(builder).build()); @@ -241,17 +234,14 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper MPJLambdaWrapper selectAssociation(Class child, SFunction dtoField) { String dtoFieldName = LambdaUtils.getName(dtoField); Class dtoClass = LambdaUtils.getEntityClass(dtoField); - Map fieldMap = ReflectionKit.getFieldMap(dtoClass); + Map fieldMap = MPJReflectionKit.getFieldMap(dtoClass); Field field = fieldMap.get(dtoFieldName); Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类"); - if (ReflectionKit.isPrimitiveOrWrapper(field.getType())) { - throw new MPJException("association 不支持基本数据类型"); - } this.resultMap = true; MybatisLabel.Builder builder; builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class) field.getType(), true); @@ -262,18 +252,15 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper MPJLambdaWrapper selectAssociation(Class child, SFunction dtoField, MFunc> collection) { String dtoFieldName = LambdaUtils.getName(dtoField); Class dtoClass = LambdaUtils.getEntityClass(dtoField); - Field field = ReflectionKit.getFieldMap(dtoClass).get(dtoFieldName); + Field field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName); this.resultMap = true; Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类"); - if (ReflectionKit.isPrimitiveOrWrapper(field.getType())) { - throw new MPJException("association 不支持基本数据类型"); - } MybatisLabel.Builder builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class) child, false); this.resultMapMybatisLabel.add(collection.apply(builder).build()); return typedThis; diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/resultmap/MybatisLabel.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/resultmap/MybatisLabel.java index 59d2093..4e80bc8 100644 --- a/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/resultmap/MybatisLabel.java +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/resultmap/MybatisLabel.java @@ -6,9 +6,8 @@ import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.toolkit.Assert; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; -import com.github.yulichang.exception.MPJException; import com.github.yulichang.toolkit.LambdaUtils; -import com.github.yulichang.toolkit.ReflectionKit; +import com.github.yulichang.toolkit.MPJReflectionKit; import lombok.Getter; import java.lang.reflect.Field; @@ -23,7 +22,7 @@ import java.util.stream.Collectors; * collection 标签 目前先支持这几个属性 后续在扩展 * * @author yulichang - * @since 1.2.5 + * @since 1.3.0 */ @Getter public class MybatisLabel { @@ -120,18 +119,15 @@ public class MybatisLabel { public > Builder collection(Class entityClass, SFunction func) { String dtoFieldName = LambdaUtils.getName(func); Class dtoClass = LambdaUtils.getEntityClass(func); - Map fieldMap = ReflectionKit.getFieldMap(dtoClass); + Map fieldMap = MPJReflectionKit.getFieldMap(dtoClass); Field field = fieldMap.get(dtoFieldName); - Class genericType = ReflectionKit.getGenericType(field); + Class genericType = MPJReflectionKit.getGenericType(field); MybatisLabel.Builder builder; if (genericType == null || genericType.isAssignableFrom(entityClass)) { //找不到集合泛型 List List List , 直接查询数据库实体 builder = new Builder<>(dtoFieldName, entityClass, field.getType()); } else { Class ofType = (Class) genericType; - if (ReflectionKit.isPrimitiveOrWrapper(ofType)) { - throw new MPJException("collection 不支持基本数据类型"); - } builder = new Builder<>(dtoFieldName, entityClass, field.getType(), ofType, true); } mybatisLabel.mybatisLabels.add(builder.build()); @@ -144,9 +140,9 @@ public class MybatisLabel { public > Builder collection(Class entityClass, SFunction func, MFunc> mFunc) { String dtoFieldName = LambdaUtils.getName(func); Class dtoClass = LambdaUtils.getEntityClass(func); - Field field = ReflectionKit.getFieldMap(dtoClass).get(dtoFieldName); + Field field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName); //获取集合泛型 - Class genericType = ReflectionKit.getGenericType(field); + Class genericType = MPJReflectionKit.getGenericType(field); Class ofType = (Class) genericType; MybatisLabel.Builder builder = new MybatisLabel.Builder<>(dtoFieldName, entityClass, field.getType(), ofType, false); mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build()); @@ -158,13 +154,10 @@ public class MybatisLabel { */ public Builder association(Class child, SFunction dtoField) { Class dtoClass = LambdaUtils.getEntityClass(dtoField); - Map fieldMap = ReflectionKit.getFieldMap(dtoClass); + Map fieldMap = MPJReflectionKit.getFieldMap(dtoClass); String dtoFieldName = LambdaUtils.getName(dtoField); Field field = fieldMap.get(dtoFieldName); Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类"); - if (ReflectionKit.isPrimitiveOrWrapper(field.getType())) { - throw new MPJException("association 不支持基本数据类型"); - } MybatisLabel.Builder builder; builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class) field.getType(), true); mybatisLabel.mybatisLabels.add(builder.build()); @@ -178,11 +171,8 @@ public class MybatisLabel { MFunc> collection) { String dtoFieldName = LambdaUtils.getName(dtoField); Class dtoClass = LambdaUtils.getEntityClass(dtoField); - Field field = ReflectionKit.getFieldMap(dtoClass).get(dtoFieldName); + Field field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName); Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类"); - if (ReflectionKit.isPrimitiveOrWrapper(field.getType())) { - throw new MPJException("association 不支持基本数据类型"); - } MybatisLabel.Builder builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class) child, false); mybatisLabel.mybatisLabels.add(collection.apply(builder).build()); return this; @@ -198,7 +188,7 @@ public class MybatisLabel { private void autoBuild(boolean auto, Class entityClass, Class tagClass) { TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass); - Map tagMap = ReflectionKit.getFieldMap(tagClass); + Map tagMap = MPJReflectionKit.getFieldMap(tagClass); if (auto && !tagMap.isEmpty()) { Function build = field -> { Result result = new Result(); diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/resultmap/Result.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/resultmap/Result.java index 99675e7..6105c79 100644 --- a/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/resultmap/Result.java +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/resultmap/Result.java @@ -17,7 +17,7 @@ import org.apache.ibatis.type.TypeHandler; * result 标签 * * @author yulichang - * @since 1.2.5 + * @since 1.3.0 */ @Getter @Setter(AccessLevel.PACKAGE) diff --git a/mybatis-plus-join-test/pom.xml b/mybatis-plus-join-test/pom.xml index 3317236..bd13058 100644 --- a/mybatis-plus-join-test/pom.xml +++ b/mybatis-plus-join-test/pom.xml @@ -9,6 +9,7 @@ mybatis-plus-join-root 2.0.0 + 2.0.0 mybatis-plus-join-test mybatis-plus-join-test @@ -70,24 +71,35 @@ com.baomidou mybatis-plus-boot-starter - ${mybatis-plus.version} + + 3.4.2 com.github.yulichang mybatis-plus-join-boot-starter - ${mybaits-plus-join.version} + 2.0.0 - - com.github.pagehelper - pagehelper-spring-boot-starter - 1.4.5 - + + + + + com.fasterxml.jackson.core jackson-databind 2.14.0 + + org.springframework + spring-jdbc + 5.3.4 + + + + + + \ No newline at end of file diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/Application.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/Application.java new file mode 100644 index 0000000..b8b9aee --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/Application.java @@ -0,0 +1,9 @@ +package com.github.yulichang.test.collection; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + + +@SpringBootApplication +public class Application { + +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/CollectionTest.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/CollectionTest.java new file mode 100644 index 0000000..7487c66 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/CollectionTest.java @@ -0,0 +1,47 @@ +package com.github.yulichang.test.collection; + +import com.github.yulichang.test.collection.dto.TableADTO; +import com.github.yulichang.test.collection.dto.TableBDTO; +import com.github.yulichang.test.collection.dto.TableCDTO; +import com.github.yulichang.test.collection.dto.TableDDTO; +import com.github.yulichang.test.collection.entity.*; +import com.github.yulichang.test.collection.mapper.TableAMapper; +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.List; + +/** + * 连表测试类 + *

+ * 支持mybatis-plus 查询枚举字段 + * 支持mybatis-plus typeHandle功能 + *

+ * 移除了mybatis-plus 逻辑删除支持,逻辑删除需要在连表查询时自己添加对应的条件 + */ +@SuppressWarnings("unused") +@SpringBootTest(properties = "spring.profiles.active=collection") +class CollectionTest { + @Resource + private TableAMapper tableAMapper; + + @Test + void testJoinCollection() { + //4层嵌套 a对多b b对多c c对多d d对多e + MPJLambdaWrapper wrapper = new MPJLambdaWrapper() + .selectAll(TableA.class) + .selectCollection(TableB.class, TableADTO::getBList, b -> b + .collection(TableC.class, TableBDTO::getCcList, c -> c + .collection(TableD.class, TableCDTO::getDList, d -> d + .collection(TableE.class, TableDDTO::getEList)))) + .leftJoin(TableB.class, TableB::getAid, TableA::getId) + .leftJoin(TableC.class, TableC::getBid, TableB::getId) + .leftJoin(TableD.class, TableD::getCid, TableC::getId) + .leftJoin(TableE.class, TableE::getDid, TableD::getId); + + List dtos = tableAMapper.selectJoinList(TableADTO.class, wrapper); + System.out.println(dtos); + } +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/config/MybatisPlusConfig.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/config/MybatisPlusConfig.java new file mode 100644 index 0000000..f3600a4 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/config/MybatisPlusConfig.java @@ -0,0 +1,24 @@ +package com.github.yulichang.test.collection.config; + +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * mybatis-plus配置 + */ +@Configuration +public class MybatisPlusConfig { + + /** + * 分页插件 + */ + @Bean + public MybatisPlusInterceptor paginationInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + PaginationInnerInterceptor page = new PaginationInnerInterceptor(); + interceptor.addInnerInterceptor(page); + return interceptor; + } +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableADTO.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableADTO.java new file mode 100644 index 0000000..baec4bb --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableADTO.java @@ -0,0 +1,17 @@ +package com.github.yulichang.test.collection.dto; + +import lombok.Data; +import lombok.ToString; + +import java.util.List; + +@Data +@ToString +public class TableADTO { + + private Integer id; + + private String name; + + private List bList; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableBDTO.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableBDTO.java new file mode 100644 index 0000000..b8643b5 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableBDTO.java @@ -0,0 +1,19 @@ +package com.github.yulichang.test.collection.dto; + +import lombok.Data; +import lombok.ToString; + +import java.util.List; + +@Data +@ToString +public class TableBDTO { + + private Integer id; + + private Integer aid; + + private String name; + + private List ccList; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableCDTO.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableCDTO.java new file mode 100644 index 0000000..cb4c573 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableCDTO.java @@ -0,0 +1,19 @@ +package com.github.yulichang.test.collection.dto; + +import lombok.Data; +import lombok.ToString; + +import java.util.List; + +@Data +@ToString +public class TableCDTO { + + private Integer id; + + private Integer bid; + + private String name; + + private List dList; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableDDTO.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableDDTO.java new file mode 100644 index 0000000..202eaf8 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableDDTO.java @@ -0,0 +1,19 @@ +package com.github.yulichang.test.collection.dto; + +import lombok.Data; +import lombok.ToString; + +import java.util.List; + +@Data +@ToString +public class TableDDTO { + + private Integer id; + + private Integer cid; + + private String name; + + private List eList; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableEDTO.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableEDTO.java new file mode 100644 index 0000000..ed47f67 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/dto/TableEDTO.java @@ -0,0 +1,15 @@ +package com.github.yulichang.test.collection.dto; + +import lombok.Data; +import lombok.ToString; + +@Data +@ToString +public class TableEDTO { + + private Integer id; + + private Integer did; + + private String name; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableA.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableA.java new file mode 100644 index 0000000..70209bc --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableA.java @@ -0,0 +1,15 @@ +package com.github.yulichang.test.collection.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("table_a") +public class TableA { + + @TableId + private Integer id; + + private String name; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableB.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableB.java new file mode 100644 index 0000000..bac6d48 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableB.java @@ -0,0 +1,17 @@ +package com.github.yulichang.test.collection.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("table_b") +public class TableB { + + @TableId + private Integer id; + + private Integer aid; + + private String name; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableC.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableC.java new file mode 100644 index 0000000..f2d8c30 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableC.java @@ -0,0 +1,17 @@ +package com.github.yulichang.test.collection.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("table_c") +public class TableC { + + @TableId + private Integer id; + + private Integer bid; + + private String name; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableD.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableD.java new file mode 100644 index 0000000..a73ac1d --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableD.java @@ -0,0 +1,17 @@ +package com.github.yulichang.test.collection.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("table_d") +public class TableD { + + @TableId + private Integer id; + + private Integer cid; + + private String name; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableE.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableE.java new file mode 100644 index 0000000..6299c75 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/entity/TableE.java @@ -0,0 +1,17 @@ +package com.github.yulichang.test.collection.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("table_e") +public class TableE { + + @TableId + private Integer id; + + private Integer did; + + private String name; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/enums/Sex.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/enums/Sex.java new file mode 100644 index 0000000..a5382ee --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/enums/Sex.java @@ -0,0 +1,24 @@ +package com.github.yulichang.test.collection.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import lombok.Getter; +import lombok.ToString; + +@Getter +@ToString +public enum Sex { + + MAN(0, "男"), + + WOMAN(1, "女"); + + @EnumValue + private final int code; + private final String des; + + Sex(int code, String des) { + this.code = code; + this.des = des; + } + +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableAMapper.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableAMapper.java new file mode 100644 index 0000000..1c71440 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableAMapper.java @@ -0,0 +1,10 @@ +package com.github.yulichang.test.collection.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.test.collection.entity.TableA; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface TableAMapper extends MPJBaseMapper { + +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableBMapper.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableBMapper.java new file mode 100644 index 0000000..c6680f0 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableBMapper.java @@ -0,0 +1,11 @@ +package com.github.yulichang.test.collection.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.test.collection.entity.TableB; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +@SuppressWarnings("unused") +public interface TableBMapper extends MPJBaseMapper { + +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableCMapper.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableCMapper.java new file mode 100644 index 0000000..148903d --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableCMapper.java @@ -0,0 +1,11 @@ +package com.github.yulichang.test.collection.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.test.collection.entity.TableC; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +@SuppressWarnings("unused") +public interface TableCMapper extends MPJBaseMapper { + +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableDMapper.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableDMapper.java new file mode 100644 index 0000000..97532cd --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableDMapper.java @@ -0,0 +1,11 @@ +package com.github.yulichang.test.collection.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.test.collection.entity.TableD; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +@SuppressWarnings("unused") +public interface TableDMapper extends MPJBaseMapper { + +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableEMapper.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableEMapper.java new file mode 100644 index 0000000..10964ff --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/collection/mapper/TableEMapper.java @@ -0,0 +1,11 @@ +package com.github.yulichang.test.collection.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.test.collection.entity.TableE; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +@SuppressWarnings("unused") +public interface TableEMapper extends MPJBaseMapper { + +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/LambdaWrapperTest.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/LambdaWrapperTest.java index a1b9593..7dae67e 100644 --- a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/LambdaWrapperTest.java +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/LambdaWrapperTest.java @@ -11,7 +11,6 @@ import com.github.yulichang.test.join.entity.UserDO; import com.github.yulichang.test.join.mapper.UserMapper; import com.github.yulichang.toolkit.MPJWrappers; import com.github.yulichang.wrapper.MPJLambdaWrapper; -import org.apache.ibatis.session.SqlSessionFactory; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @@ -32,16 +31,9 @@ import java.util.Map; class LambdaWrapperTest { @Resource private UserMapper userMapper; - @Resource - private SqlSessionFactory sqlSessionFactory; - /** - * 一对多 - */ @Test void testJoin() { - userMapper.selectListDeep(new QueryWrapper<>()); - MPJLambdaWrapper wrapper = new MPJLambdaWrapper() .selectAll(UserDO.class) .selectCollection(AddressDO.class, UserDTO::getAddressList, addr -> addr @@ -109,6 +101,7 @@ class LambdaWrapperTest { */ @Test void test6() { + userMapper.selectPage(new Page<>(1, 10),new QueryWrapper<>()); IPage page = userMapper.selectJoinPage(new Page<>(1, 10), UserDTO.class, MPJWrappers.lambdaJoin() .selectAll(UserDO.class) diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/dto/TableDTO.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/dto/TableDTO.java new file mode 100644 index 0000000..c3d6aae --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/dto/TableDTO.java @@ -0,0 +1,61 @@ +package com.github.yulichang.test.join.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class TableDTO { + + private Integer id; + + private String name; + + private List bbList; + + @Data + public static class TableBDTO { + + private Integer id; + + private Integer aid; + + private String name; + + private List ccList; + } + + @Data + public static class TableCDTO { + + private Integer id; + + private Integer bid; + + private String name; + + private List ddList; + } + + @Data + public static class TableDDTO { + + private Integer id; + + private Integer cid; + + private String name; + + private List eeList; + } + + @Data + public static class TableEDTO { + + private Integer id; + + private Integer did; + + private String name; + } +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableA.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableA.java new file mode 100644 index 0000000..e22d6d7 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableA.java @@ -0,0 +1,15 @@ +package com.github.yulichang.test.join.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("table_a") +public class TableA { + + @TableId + private Integer id; + + private String name; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableB.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableB.java new file mode 100644 index 0000000..80205b0 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableB.java @@ -0,0 +1,17 @@ +package com.github.yulichang.test.join.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("table_b") +public class TableB { + + @TableId + private Integer id; + + private Integer aid; + + private String name; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableC.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableC.java new file mode 100644 index 0000000..1ed74e2 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableC.java @@ -0,0 +1,17 @@ +package com.github.yulichang.test.join.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("table_c") +public class TableC { + + @TableId + private Integer id; + + private Integer bid; + + private String name; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableD.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableD.java new file mode 100644 index 0000000..c44940c --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableD.java @@ -0,0 +1,17 @@ +package com.github.yulichang.test.join.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("table_d") +public class TableD { + + @TableId + private Integer id; + + private Integer cid; + + private String name; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableE.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableE.java new file mode 100644 index 0000000..e69a7ef --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/TableE.java @@ -0,0 +1,17 @@ +package com.github.yulichang.test.join.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("table_e") +public class TableE { + + @TableId + private Integer id; + + private Integer did; + + private String name; +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/UserDO.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/UserDO.java index edcd8df..8f589a4 100644 --- a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/UserDO.java +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/entity/UserDO.java @@ -24,7 +24,7 @@ public class UserDO { private Integer id; @TableField(value = "`name`", typeHandler = JacksonTypeHandler.class) - private Map name; + private Map aName; private Sex sex; diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableAMapper.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableAMapper.java new file mode 100644 index 0000000..91a3bea --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableAMapper.java @@ -0,0 +1,11 @@ +package com.github.yulichang.test.join.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.test.join.entity.TableA; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +@SuppressWarnings("unused") +public interface TableAMapper extends MPJBaseMapper { + +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableBMapper.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableBMapper.java new file mode 100644 index 0000000..a3a2173 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableBMapper.java @@ -0,0 +1,11 @@ +package com.github.yulichang.test.join.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.test.join.entity.TableB; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +@SuppressWarnings("unused") +public interface TableBMapper extends MPJBaseMapper { + +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableCMapper.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableCMapper.java new file mode 100644 index 0000000..b74a614 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableCMapper.java @@ -0,0 +1,11 @@ +package com.github.yulichang.test.join.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.test.join.entity.TableC; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +@SuppressWarnings("unused") +public interface TableCMapper extends MPJBaseMapper { + +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableDMapper.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableDMapper.java new file mode 100644 index 0000000..2bd16d6 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableDMapper.java @@ -0,0 +1,11 @@ +package com.github.yulichang.test.join.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.test.join.entity.TableD; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +@SuppressWarnings("unused") +public interface TableDMapper extends MPJBaseMapper { + +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableEMapper.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableEMapper.java new file mode 100644 index 0000000..2f70960 --- /dev/null +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/join/mapper/TableEMapper.java @@ -0,0 +1,11 @@ +package com.github.yulichang.test.join.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.test.join.entity.TableE; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +@SuppressWarnings("unused") +public interface TableEMapper extends MPJBaseMapper { + +} diff --git a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/mapping/config/MybatisPlusConfig.java b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/mapping/config/MybatisPlusConfig.java index 83d6022..79685b5 100644 --- a/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/mapping/config/MybatisPlusConfig.java +++ b/mybatis-plus-join-test/src/test/java/com/github/yulichang/test/mapping/config/MybatisPlusConfig.java @@ -18,7 +18,6 @@ public class MybatisPlusConfig { public MybatisPlusInterceptor paginationInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); PaginationInnerInterceptor page = new PaginationInnerInterceptor(); - page.setOptimizeJoin(false); interceptor.addInnerInterceptor(page); return interceptor; } diff --git a/mybatis-plus-join-test/src/test/resources/application-collection.yml b/mybatis-plus-join-test/src/test/resources/application-collection.yml new file mode 100644 index 0000000..00f280f --- /dev/null +++ b/mybatis-plus-join-test/src/test/resources/application-collection.yml @@ -0,0 +1,5 @@ +spring: + sql: + init: + schema-locations: classpath:db/collection/schema.sql + data-locations: classpath:db/collection/data.sql \ No newline at end of file diff --git a/mybatis-plus-join-test/src/test/resources/application.yml b/mybatis-plus-join-test/src/test/resources/application.yml index 6d099dd..b0ad69e 100644 --- a/mybatis-plus-join-test/src/test/resources/application.yml +++ b/mybatis-plus-join-test/src/test/resources/application.yml @@ -6,6 +6,7 @@ spring: password: test mybatis-plus: + typeEnumsPackage: com.github.yulichang.test global-config: db-config: logic-delete-field: del diff --git a/mybatis-plus-join-test/src/test/resources/db/collection/data.sql b/mybatis-plus-join-test/src/test/resources/db/collection/data.sql new file mode 100644 index 0000000..8e9b4c1 --- /dev/null +++ b/mybatis-plus-join-test/src/test/resources/db/collection/data.sql @@ -0,0 +1,29 @@ +-- noinspection SqlDialectInspectionForFile + +-- noinspection SqlNoDataSourceInspectionForFile + +DELETE FROM table_a; +insert into table_a (id, `name`) values (1, 'tableA1'); +insert into table_a (id, `name`) values (2, 'tableA2'); +insert into table_a (id, `name`) values (3, 'tableA3'); + +DELETE FROM table_b; +insert into table_b (id, aid, `name`) values (1, 1, 'tableB1'); +insert into table_b (id, aid, `name`) values (2, 1, 'tableB2'); +insert into table_b (id, aid, `name`) values (3, 2, 'tableB3'); + +DELETE FROM table_c; +insert into table_c (id, bid, `name`) values (1, 1, 'tableC1'); +insert into table_c (id, bid, `name`) values (2, 1, 'tableC2'); +insert into table_c (id, bid, `name`) values (3, 2, 'tableC3'); + +DELETE FROM table_d; +insert into table_d (id, cid, `name`) values (1, 1, 'tableD1'); +insert into table_d (id, cid, `name`) values (2, 1, 'tableD2'); +insert into table_d (id, cid, `name`) values (3, 2, 'tableD3'); + +DELETE FROM table_e; +insert into table_e (id, did, `name`) values (1, 1, 'tableE1'); +insert into table_e (id, did, `name`) values (2, 1, 'tableE2'); +insert into table_e (id, did, `name`) values (3, 2, 'tableE3'); + diff --git a/mybatis-plus-join-test/src/test/resources/db/collection/schema.sql b/mybatis-plus-join-test/src/test/resources/db/collection/schema.sql new file mode 100644 index 0000000..d8a1fc8 --- /dev/null +++ b/mybatis-plus-join-test/src/test/resources/db/collection/schema.sql @@ -0,0 +1,48 @@ +-- noinspection SqlDialectInspectionForFile + +-- noinspection SqlNoDataSourceInspectionForFile + + +DROP TABLE IF EXISTS table_a; +create table table_a +( + id int auto_increment + primary key, + `name` varchar(255) null +); + +DROP TABLE IF EXISTS table_b; +create table table_b +( + id int auto_increment + primary key, + `aid` int not null, + `name` varchar(255) null +); + +DROP TABLE IF EXISTS table_c; +create table table_c +( + id int auto_increment + primary key, + `bid` int not null, + `name` varchar(255) null +); + +DROP TABLE IF EXISTS table_d; +create table table_d +( + id int auto_increment + primary key, + `cid` int not null, + `name` varchar(255) null +); + +DROP TABLE IF EXISTS table_e; +create table table_e +( + id int auto_increment + primary key, + `did` int not null, + `name` varchar(255) null +); \ No newline at end of file diff --git a/mybatis-plus-join-test/src/test/resources/db/join/data.sql b/mybatis-plus-join-test/src/test/resources/db/join/data.sql index 2f8baa0..6bd397b 100644 --- a/mybatis-plus-join-test/src/test/resources/db/join/data.sql +++ b/mybatis-plus-join-test/src/test/resources/db/join/data.sql @@ -76,4 +76,5 @@ INSERT INTO address (id, user_id, area_id, tel, address, del) VALUES (18,18, 100 INSERT INTO address (id, user_id, area_id, tel, address, del) VALUES (19,19, 10019, '10000000019', '曹县19', false); INSERT INTO address (id, user_id, area_id, tel, address, del) VALUES (20,20, 10020, '10000000020', '曹县20', false); INSERT INTO address (id, user_id, area_id, tel, address, del) VALUES (21,21, 10021, '10000000021', '曹县21', false); -INSERT INTO address (id, user_id, area_id, tel, address, del) VALUES (22,22, 10022, '10000000022', '曹县22', false); \ No newline at end of file +INSERT INTO address (id, user_id, area_id, tel, address, del) VALUES (22,22, 10022, '10000000022', '曹县22', false); + diff --git a/mybatis-plus-join-test/src/test/resources/db/join/schema.sql b/mybatis-plus-join-test/src/test/resources/db/join/schema.sql index 264b2ea..f728079 100644 --- a/mybatis-plus-join-test/src/test/resources/db/join/schema.sql +++ b/mybatis-plus-join-test/src/test/resources/db/join/schema.sql @@ -12,20 +12,20 @@ create table area city varchar(255) null, area varchar(255) null, postcode varchar(255) null, - del bit + del bit ); DROP TABLE IF EXISTS `user`; create table `user` ( - id int auto_increment + id int auto_increment primary key, - `name` varchar(255) not null, - `address_id` int not null, - sex tinyint not null, - head_img varchar(255) not null, - del bit + `name` varchar(255) not null, + `address_id` int not null, + sex tinyint not null, + head_img varchar(255) not null, + del bit ); DROP TABLE IF EXISTS address; @@ -34,9 +34,9 @@ create table address ( id int auto_increment primary key, - user_id int null, - area_id int null, + user_id int null, + area_id int null, tel varchar(255) null, address varchar(255) null, - del bit + del bit ); \ No newline at end of file