mirror of
https://gitee.com/best_handsome/mybatis-plus-join
synced 2025-07-11 00:02:22 +08:00
同步 mybatis plus 3.5.2 代码
This commit is contained in:
parent
efcccd2da0
commit
9464dea9f2
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--suppress ALL -->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
@ -8,6 +9,7 @@
|
||||
<artifactId>mybatis-plus-join-root</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<version>2.0.0</version>
|
||||
<artifactId>mybatis-plus-join-annotation</artifactId>
|
||||
<name>mybatis-plus-join-annotation</name>
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--suppress ALL -->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
@ -8,6 +9,7 @@
|
||||
<artifactId>mybatis-plus-join-root</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<version>2.0.0</version>
|
||||
<artifactId>mybatis-plus-join-boot-starter</artifactId>
|
||||
<name>mybatis-plus-join-boot-starter</name>
|
||||
|
||||
@ -45,7 +47,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
<artifactId>mybatis-plus-join-core</artifactId>
|
||||
<version>${mybaits-plus-join.version}</version>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
@ -9,6 +9,7 @@
|
||||
<artifactId>mybatis-plus-join-root</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<version>2.0.0</version>
|
||||
<artifactId>mybatis-plus-join-core</artifactId>
|
||||
<name>mybatis-plus-join-core</name>
|
||||
|
||||
@ -46,7 +47,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
<artifactId>mybatis-plus-join-annotation</artifactId>
|
||||
<version>${mybaits-plus-join.version}</version>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
@ -60,6 +61,12 @@
|
||||
<version>${lombok.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
<version>2.0.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
|
@ -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<?, ?>> mybatisLabel, Set<String> columnSet,
|
||||
List<ResultMapping> parentMappings, List<SelectColumn> columnList) {
|
||||
for (MybatisLabel<?, ?> mpjColl : mybatisLabel) {
|
||||
List<Result> list = mpjColl.getResultList();
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
continue;
|
||||
|
||||
//fix 重上往下会有resultMap覆盖问题,应该从根节点开始,id向上传递
|
||||
|
||||
/**
|
||||
* @return 返回节点id
|
||||
*/
|
||||
private ResultMapping buildResult(MappedStatement ms, MybatisLabel<?, ?> mybatisLabel, Set<String> columnSet,
|
||||
List<SelectColumn> columnList) {
|
||||
List<Result> resultList = mybatisLabel.getResultList();
|
||||
if (CollectionUtils.isEmpty(resultList)) {
|
||||
return null;
|
||||
}
|
||||
List<ResultMapping> 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<ResultMapping> 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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* ClassUtils
|
||||
* </p>
|
||||
*
|
||||
* @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<String> 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 获取当前对象的 class
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 获取当前对象的class
|
||||
* </p>
|
||||
*
|
||||
* @param object 对象
|
||||
* @return 返回对象的 user class
|
||||
*/
|
||||
public static Class<?> getUserClass(Object object) {
|
||||
Assert.notNull(object, "Instance must not be null");
|
||||
return getUserClass(object.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据指定的 class , 实例化一个对象,根据构造参数来实例化
|
||||
* </p>
|
||||
* <p>
|
||||
* 在 java9 及其之后的版本 Class.newInstance() 方法已被废弃
|
||||
* </p>
|
||||
*
|
||||
* @param clazz 需要实例化的对象
|
||||
* @param <T> 类型,由输入类型决定
|
||||
* @return 返回新的实例
|
||||
*/
|
||||
public static <T> T newInstance(Class<T> clazz) {
|
||||
try {
|
||||
Constructor<T> 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 <T> 类型
|
||||
* @return 实例
|
||||
* @since 3.3.2
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T newInstance(String clazzName) {
|
||||
return (T) newInstance(toClassConfident(clazzName));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 请仅在确定类存在的情况下调用该方法
|
||||
* </p>
|
||||
*
|
||||
* @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.
|
||||
* <p>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};
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ import java.util.function.Predicate;
|
||||
* 保证 MPJInterceptor 再最后一个(第一个执行)
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.2.5
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class InterceptorList<E extends Interceptor> extends ArrayList<E> {
|
||||
|
||||
|
@ -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 <T> String getName(SFunction<T, ?> fn) {
|
||||
return PropertyNamer.methodToProperty(resolve(fn).getImplMethodName());
|
||||
LambdaMeta extract = extract(fn);
|
||||
String name = PropertyNamer.methodToProperty(extract.getImplMethodName());
|
||||
if (Character.isUpperCase(name.charAt(0))) {
|
||||
Map<String, Field> 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 <T> Class<T> getEntityClass(SFunction<T, ?> fn) {
|
||||
return (Class<T>) resolve(fn).getInstantiatedType();
|
||||
return (Class<T>) extract(fn).getInstantiatedClass();
|
||||
}
|
||||
/* ******* 自定义方法 结束 以下代码均为拷贝 *********** */
|
||||
|
||||
|
||||
/**
|
||||
* 字段映射
|
||||
*/
|
||||
private static final Map<String, Map<String, ColumnCache>> COLUMN_CACHE_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* SerializedLambda 反序列化缓存
|
||||
*/
|
||||
private static final Map<String, WeakReference<SerializedLambda>> FUNC_CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 解析 lambda 表达式, 该方法只是调用了 {@link SerializedLambda#resolve(SFunction)} 中的方法,在此基础上加了缓存。
|
||||
* 该缓存可能会在任意不定的时间被清除
|
||||
*
|
||||
* @param func 需要解析的 lambda 对象
|
||||
* @param <T> 类型,被调用的 Function 对象的目标类型
|
||||
* @return 返回解析后的结果
|
||||
* @see SerializedLambda#resolve(SFunction)
|
||||
*/
|
||||
public static <T> SerializedLambda resolve(SFunction<T, ?> 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 <T> LambdaMeta extract(SFunction<T, ?> 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);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<Class<?>, Map<String, Field>> 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<String, Field> getFieldMap(Class<?> clazz) {
|
||||
if (clazz == null) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
Map<String, Field> fieldMap = CLASS_FIELD_CACHE.get(clazz);
|
||||
if (fieldMap != null) {
|
||||
return fieldMap;
|
||||
}
|
||||
Map<String, Field> map = ReflectionKit.getFieldMap(clazz);
|
||||
CLASS_FIELD_CACHE.put(clazz, map);
|
||||
return map;
|
||||
}
|
||||
}
|
@ -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<Class<?>, List<Field>> CLASS_FIELD_CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
@Deprecated
|
||||
private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_TYPE_MAP = new IdentityHashMap<>(8);
|
||||
|
||||
private static final Map<Class<?>, Class<?>> PRIMITIVE_TYPE_TO_WRAPPER_MAP = new IdentityHashMap<>(8);
|
||||
@ -83,26 +84,20 @@ public final class ReflectionKit {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collection字段的泛型
|
||||
* <p>
|
||||
* 反射对象获取泛型
|
||||
* </p>
|
||||
*
|
||||
* @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<String, Field> getFieldMap(Class<?> clazz) {
|
||||
List<Field> 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<String, Field> excludeOverrideSuperField(Field[] fields, List<Field> superFieldList) {
|
||||
// 子类属性
|
||||
Map<String, Field> 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 <T> 类型
|
||||
* @return 返回设置后的对象
|
||||
*/
|
||||
public static <T extends AccessibleObject> T setAccessible(T object) {
|
||||
return AccessController.doPrivileged(new SetAccessibleAction<>(object));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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 表达式元数据需要使用该类处理元数据
|
||||
* <p>
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
@ -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 信息
|
||||
* <p>
|
||||
* Created by hcl at 2021/5/14
|
||||
*/
|
||||
public interface LambdaMeta {
|
||||
|
||||
/**
|
||||
* 获取 lambda 表达式实现方法的名称
|
||||
*
|
||||
* @return lambda 表达式对应的实现方法名称
|
||||
*/
|
||||
String getImplMethodName();
|
||||
|
||||
/**
|
||||
* 实例化该方法的类
|
||||
*
|
||||
* @return 返回对应的类名称
|
||||
*/
|
||||
Class<?> getInstantiatedClass();
|
||||
|
||||
}
|
@ -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<SerializedLambda> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -9,7 +9,7 @@ import lombok.Getter;
|
||||
* MPJLambdaWrapper 查询字段
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.2.5
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Getter
|
||||
public class SelectColumn {
|
||||
|
@ -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 } 的一个镜像
|
||||
* <p>
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
@ -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} 创建的元信息
|
||||
* <p>
|
||||
* 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());
|
||||
}
|
||||
|
||||
}
|
@ -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<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
||||
* <pre/>
|
||||
* 会自动将 UserAddressDO类中相同属性的字段 以mybatis<collection>的方式映射到UserDTO.addressListDTO属性中
|
||||
*
|
||||
* @since 1.2.5
|
||||
* @since 1.3.0
|
||||
*
|
||||
* @param child 连表数据库实体类
|
||||
* @param dtoField 包装类对应的属性
|
||||
@ -177,19 +173,16 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
||||
public <S, C, Z, F extends java.util.Collection<?>> MPJLambdaWrapper<T> selectCollection(Class<C> child, SFunction<S, F> dtoField) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
Map<String, Field> fieldMap = ReflectionKit.getFieldMap(dtoClass);
|
||||
Map<String, Field> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||
Field field = fieldMap.get(dtoFieldName);
|
||||
this.resultMap = true;
|
||||
Class<?> genericType = ReflectionKit.getGenericType(field);
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field);
|
||||
MybatisLabel.Builder<C, Z> builder;
|
||||
if (genericType == null || genericType.isAssignableFrom(child)) {
|
||||
//找不到集合泛型 List List<?> List<Object> , 直接查询数据库实体
|
||||
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType());
|
||||
} else {
|
||||
Class<Z> ofType = (Class<Z>) 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<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
||||
*
|
||||
* 会自动将 UserAddressDO类中指定的字段 以mybatis<collection>的方式映射到UserDTO.addressListDTO属性中
|
||||
*
|
||||
* @since 1.2.5
|
||||
* @since 1.3.0
|
||||
*
|
||||
* @param child 连表数据库实体类
|
||||
* @param dtoField 包装类对应的属性
|
||||
@ -228,10 +221,10 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
||||
selectCollection(Class<C> child, SFunction<S, F> dtoField, MFunc<MybatisLabel.Builder<C, Z>> collection) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<S> 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<Z> ofType = (Class<Z>) genericType;
|
||||
MybatisLabel.Builder<C, Z> builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), ofType, false);
|
||||
this.resultMapMybatisLabel.add(collection.apply(builder).build());
|
||||
@ -241,17 +234,14 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
||||
/**
|
||||
* 对一查询 用法参考 selectCollection
|
||||
*
|
||||
* @since 1.2.5
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public <S, C, F> MPJLambdaWrapper<T> selectAssociation(Class<C> child, SFunction<S, F> dtoField) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
Map<String, Field> fieldMap = ReflectionKit.getFieldMap(dtoClass);
|
||||
Map<String, Field> 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<C, F> builder;
|
||||
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<F>) field.getType(), true);
|
||||
@ -262,18 +252,15 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
|
||||
/**
|
||||
* 对一查询 用法参考 selectCollection
|
||||
*
|
||||
* @since 1.2.5
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public <S, C, F> MPJLambdaWrapper<T> selectAssociation(Class<C> child, SFunction<S, F> dtoField,
|
||||
MFunc<MybatisLabel.Builder<C, F>> collection) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<S> 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<C, F> builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<F>) child, false);
|
||||
this.resultMapMybatisLabel.add(collection.apply(builder).build());
|
||||
return typedThis;
|
||||
|
@ -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<E, T> {
|
||||
@ -120,18 +119,15 @@ public class MybatisLabel<E, T> {
|
||||
public <A, R, B extends Collection<R>> Builder<E, T> collection(Class<A> entityClass, SFunction<T, B> func) {
|
||||
String dtoFieldName = LambdaUtils.getName(func);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||
Map<String, Field> fieldMap = ReflectionKit.getFieldMap(dtoClass);
|
||||
Map<String, Field> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||
Field field = fieldMap.get(dtoFieldName);
|
||||
Class<?> genericType = ReflectionKit.getGenericType(field);
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field);
|
||||
MybatisLabel.Builder<A, R> builder;
|
||||
if (genericType == null || genericType.isAssignableFrom(entityClass)) {
|
||||
//找不到集合泛型 List List<?> List<Object> , 直接查询数据库实体
|
||||
builder = new Builder<>(dtoFieldName, entityClass, field.getType());
|
||||
} else {
|
||||
Class<R> ofType = (Class<R>) 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<E, T> {
|
||||
public <A, R, B extends Collection<R>> Builder<E, T> collection(Class<A> entityClass, SFunction<T, B> func, MFunc<Builder<A, R>> mFunc) {
|
||||
String dtoFieldName = LambdaUtils.getName(func);
|
||||
Class<T> 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<R> ofType = (Class<R>) genericType;
|
||||
MybatisLabel.Builder<A, R> builder = new MybatisLabel.Builder<>(dtoFieldName, entityClass, field.getType(), ofType, false);
|
||||
mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build());
|
||||
@ -158,13 +154,10 @@ public class MybatisLabel<E, T> {
|
||||
*/
|
||||
public <A, B> Builder<E, T> association(Class<A> child, SFunction<T, B> dtoField) {
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
Map<String, Field> fieldMap = ReflectionKit.getFieldMap(dtoClass);
|
||||
Map<String, Field> 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<A, B> builder;
|
||||
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<B>) field.getType(), true);
|
||||
mybatisLabel.mybatisLabels.add(builder.build());
|
||||
@ -178,11 +171,8 @@ public class MybatisLabel<E, T> {
|
||||
MFunc<MybatisLabel.Builder<A, B>> collection) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<T> 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<A, B> builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<B>) child, false);
|
||||
mybatisLabel.mybatisLabels.add(collection.apply(builder).build());
|
||||
return this;
|
||||
@ -198,7 +188,7 @@ public class MybatisLabel<E, T> {
|
||||
|
||||
private void autoBuild(boolean auto, Class<E> entityClass, Class<T> tagClass) {
|
||||
TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
|
||||
Map<String, Field> tagMap = ReflectionKit.getFieldMap(tagClass);
|
||||
Map<String, Field> tagMap = MPJReflectionKit.getFieldMap(tagClass);
|
||||
if (auto && !tagMap.isEmpty()) {
|
||||
Function<TableFieldInfo, Result> build = field -> {
|
||||
Result result = new Result();
|
||||
|
@ -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)
|
||||
|
@ -9,6 +9,7 @@
|
||||
<artifactId>mybatis-plus-join-root</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<version>2.0.0</version>
|
||||
<artifactId>mybatis-plus-join-test</artifactId>
|
||||
<name>mybatis-plus-join-test</name>
|
||||
|
||||
@ -70,24 +71,35 @@
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
<!-- <version>${mybatis-plus.version}</version>-->
|
||||
<version>3.4.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
<artifactId>mybatis-plus-join-boot-starter</artifactId>
|
||||
<version>${mybaits-plus-join.version}</version>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
<!-- PageHelper 兼容性测试 -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
<version>1.4.5</version>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.github.pagehelper</groupId>-->
|
||||
<!-- <artifactId>pagehelper-spring-boot-starter</artifactId>-->
|
||||
<!-- <version>1.4.5</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.14.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>5.3.4</version>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>jsqlparser</groupId>-->
|
||||
<!-- <artifactId>jsqlparser</artifactId>-->
|
||||
<!-- <version>0.7.0</version>-->
|
||||
<!-- </dependency>-->
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,9 @@
|
||||
package com.github.yulichang.test.collection;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* 连表测试类
|
||||
* <p>
|
||||
* 支持mybatis-plus 查询枚举字段
|
||||
* 支持mybatis-plus typeHandle功能
|
||||
* <p>
|
||||
* 移除了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<TableA> wrapper = new MPJLambdaWrapper<TableA>()
|
||||
.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<TableADTO> dtos = tableAMapper.selectJoinList(TableADTO.class, wrapper);
|
||||
System.out.println(dtos);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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<TableBDTO> bList;
|
||||
}
|
@ -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<TableCDTO> ccList;
|
||||
}
|
@ -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<TableDDTO> dList;
|
||||
}
|
@ -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<TableEDTO> eList;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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<TableA> {
|
||||
|
||||
}
|
@ -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<TableB> {
|
||||
|
||||
}
|
@ -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<TableC> {
|
||||
|
||||
}
|
@ -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<TableD> {
|
||||
|
||||
}
|
@ -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<TableE> {
|
||||
|
||||
}
|
@ -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<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
|
||||
.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<UserDTO> page = userMapper.selectJoinPage(new Page<>(1, 10), UserDTO.class,
|
||||
MPJWrappers.<UserDO>lambdaJoin()
|
||||
.selectAll(UserDO.class)
|
||||
|
@ -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<TableBDTO> bbList;
|
||||
|
||||
@Data
|
||||
public static class TableBDTO {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private Integer aid;
|
||||
|
||||
private String name;
|
||||
|
||||
private List<TableCDTO> ccList;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class TableCDTO {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private Integer bid;
|
||||
|
||||
private String name;
|
||||
|
||||
private List<TableDDTO> ddList;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class TableDDTO {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private Integer cid;
|
||||
|
||||
private String name;
|
||||
|
||||
private List<TableEDTO> eeList;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class TableEDTO {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private Integer did;
|
||||
|
||||
private String name;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -24,7 +24,7 @@ public class UserDO {
|
||||
private Integer id;
|
||||
|
||||
@TableField(value = "`name`", typeHandler = JacksonTypeHandler.class)
|
||||
private Map<String,String> name;
|
||||
private Map<String,String> aName;
|
||||
|
||||
private Sex sex;
|
||||
|
||||
|
@ -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<TableA> {
|
||||
|
||||
}
|
@ -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<TableB> {
|
||||
|
||||
}
|
@ -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<TableC> {
|
||||
|
||||
}
|
@ -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<TableD> {
|
||||
|
||||
}
|
@ -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<TableE> {
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
spring:
|
||||
sql:
|
||||
init:
|
||||
schema-locations: classpath:db/collection/schema.sql
|
||||
data-locations: classpath:db/collection/data.sql
|
@ -6,6 +6,7 @@ spring:
|
||||
password: test
|
||||
|
||||
mybatis-plus:
|
||||
typeEnumsPackage: com.github.yulichang.test
|
||||
global-config:
|
||||
db-config:
|
||||
logic-delete-field: del
|
||||
|
@ -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');
|
||||
|
@ -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
|
||||
);
|
@ -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);
|
||||
INSERT INTO address (id, user_id, area_id, tel, address, del) VALUES (22,22, 10022, '10000000022', '曹县22', false);
|
||||
|
||||
|
@ -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
|
||||
);
|
Loading…
x
Reference in New Issue
Block a user