三、从零开始-填坑

三、从零开始-填坑

填上一章的坑,对 VO 的使用进行优化

导航

上一章地址:二、从零开始-用户管理

下一章地址:四、从零开始-优化用户管理新增

说明

  1. 贴代码时会贴整个类的全量代码,防止找不到我改的是哪个
  2. 创建的类在哪个包下不会单独说明,因为全量代码里有 package 直接看这个就可以了
  3. gitee 代码存放地址 https://gitee.com/mxw13579/study-scaffold 可以直接下下来看更加清晰

三、从零开始-填坑

3.1、填坑

上期不是还留了两个坑吗,一个是 VO 的转换,还有一个是查全量然后展示少数会浪费问题

3.1.1、VO 转换问题

这个是分为两项,一个是转换效率不高,一个是抽取公共

转换效率不高这个问题吧,怎么说呢,分页这玩意本来数据量就小,其实不改也不是不行

抽取公共的话,有两个思路,一个是去 DEBUG 跟一下他是什么时候转换为类型的,一个是写一个工具类

3.1.1.1、转换效率问题

这个的话采用 MapStruct 来做转换来处理。

别问为什么快,问就是 BeanUtil 这种方式采取的是反射向里写入数据,而 MapStruct 采取的是字节码生成一个带有 Get/Set 方法的转换方法,所以快。

当然区别只有在数据量比较大的情况下才能看出来,数据量小的话,我只能说根本没啥区别

首先导入依赖文件

<!--  mapStruct开始  -->
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.4.2.Final</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-jdk8</artifactId>
    <version>1.4.2.Final</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok-mapstruct-binding</artifactId>
    <version>0.2.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.4.2.Final</version>
</dependency>
<!--  mapStruct结束  -->

然后写一个接口

package com.lzl.study.scaffold.studyscaffold.common.mapstruct;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lzl.study.scaffold.studyscaffold.user.entity.SysUserEntity;
import com.lzl.study.scaffold.studyscaffold.user.entity.dto.SysUserPageDto;
import com.lzl.study.scaffold.studyscaffold.user.entity.dto.SysUserSaveDto;
import com.lzl.study.scaffold.studyscaffold.user.entity.vo.SysUserPageHomeVo;
import org.mapstruct.Mapper;

/**
 * @ClassName MapStructConv
 * @Author lizelin
 * @Description MapStruct 转换器
 * 规定方法格式为
 * convert+源类型+To+目标类型
 * convertSysUserEntityToSysUserPageHomeVo
 * @Date 2023-10-11 5:16
 * @Version 1.0
 */
@Mapper(componentModel = "spring")
public interface MapStructConvert {

    /**
     * @param entity
     * @return com.lzl.study.scaffold.studyscaffold.user.entity.vo.SysUserPageHomeVo
     * @Description SysUserEntity 转 SysUserPageHomeVo
     * @author lizelin
     * @date 2023-10-11 5:36
     **/
    SysUserPageHomeVo convertSysUserEntityToSysUserPageHomeVo(SysUserEntity entity);

    /**
     * @param dto
     * @return com.lzl.study.scaffold.studyscaffold.user.entity.SysUserEntity
     * @Description SysUserSaveDto 转 SysUserEntity
     * @author lizelin
     * @date 2023-10-11 6:34
     **/
    SysUserEntity convertSysUserSaveDtoToSysUserEntity(SysUserSaveDto dto);

    /**
     * @param dto
     * @return com.lzl.study.scaffold.studyscaffold.user.entity.SysUserEntity
     * @Description SysUserPageDto 转 SysUserEntity
     * @author lizelin
     * @date 2023-10-11 7:14
     **/
    SysUserEntity convertSysUserPageDtoToSysUserEntity(SysUserPageDto dto);

    /**
     * @param page
     * @return com.baomidou.mybatisplus.extension.plugins.pagination.Page
     * @Description Page 转 Page
     * @author lizelin
     * @date 2023-10-11 7:12
     **/
    Page convertPageToPage(Page page);

    /**
     * @param page
     * @return com.baomidou.mybatisplus.extension.plugins.pagination.Page
     * @Description SysUserPageDto 转 Page
     * @author lizelin
     * @date 2023-10-11 7:14
     **/
    Page convertSysUserPageDtoToPage(SysUserPageDto page);
}

说明一下写的格式

返回参数 方法名(传参)

比如说你想 A 类型转换为 B 类型

B xxxx(A)

方法名可以随便写,保证 A 类型的字段名和格式与 B 类型一致就可以了,不一致的转换方式后面用到了讲

但是在这个项目中由于使用到了反射调用,所以要按规定方法格式来写

然后 maven 打一下包,就会在 target/generated-sources/annotations/com/lzl/study/scaffold/studyscaffold/common/mapstruct/MapStructConvertImpl.java 生成一个实现类的文件

更改转换器也就搞定了

3.1.1.2、抽取公共方法

首先我们先将转换器抽取出来一个工具类

package com.lzl.study.scaffold.studyscaffold.common.mapstruct;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName MapStructConvertUtil
 * @Author lizelin
 * @Description MapStruct 转换工具类
 * @Date 2023-10-11 5:53
 * @Version 1.0
 */
public class MapStructConvertUtil {

    private MapStructConvertUtil() {
        throw new IllegalStateException("工具类不允许实例化");
    }

    private static MapStructConvert mapStructConvert;

    static {
        MapStructConvert bean = SpringUtil.getBean(MapStructConvert.class);
        MapStructConvertUtil.mapStructConvert = bean;
    }

    /**
     * @param list   分页数据
     * @param tClass 转换目标类型
     * @return java.util.List<T>
     * @Description 转换 Page 的 records
     * @author lizelin
     * @date 2023-10-11 6:38
     **/
    public static <T,E> List<T> getRecords(List<E> list, Class<T> tClass) {
        Object collect = list.stream().map(item -> mapStructConvert(item, tClass)).collect(Collectors.toList());
        return (List<T>) collect;
    }

    /**
     * @param source 源对象
     * @param tClass 目标 class
     * @return T
     * @Description 将源对象转换为 目标对象
     * @author lizelin
     * @date 2023-10-11 6:37
     **/
    public static <T> T mapStructConvert(Object source, Class<T> tClass) {
        Class<?> aClass = source.getClass();
        String sourceName = aClass.getSimpleName();
        String targetName = tClass.getSimpleName();
        //拼接方法名
        StringBuilder builder = StrUtil.builder();
        builder.append("convert");
        builder.append(sourceName);
        builder.append("To");
        builder.append(targetName);
        String me = builder.toString();
        try {
            //反射调用方法
            Method method = mapStructConvert.getClass().getMethod(me, aClass);
            Object invoke = method.invoke(mapStructConvert, source);
            return (T) invoke;
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();

        }
        return null;
    }

}

采用反射的方式去调用转换器的方法,这样一个对象只用反射一次,然后直接调用 Get/Set 方法

不过这里还可以继续改进,用一个全局缓存存储 method 这样就不用每次都去反射找 method 了

然后我们将分页转换也做一个工具类

package com.lzl.study.scaffold.studyscaffold.common.util;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lzl.study.scaffold.studyscaffold.common.mapstruct.MapStructConvertUtil;

import java.util.List;

/**
 * @ClassName PageUtil
 * @Author lizelin
 * @Description 分页工具类
 * @Date 2023-10-11 6:45
 * @Version 1.0
 */
public class PageUtil {

    private PageUtil() {
        throw new IllegalStateException("工具类不允许实例化");
    }

    /**
     * @param page
     * @param tClass
     * @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<T>
     * @Description 转换 page
     * @author lizelin
     * @date 2023-10-11 6:50
     **/
    public static <T, E> Page<T> convertPage(Page<E> page, Class<T> tClass) {

        List<E> records = page.getRecords();
        Page<T> voPage = MapStructConvertUtil.mapStructConvert(page, Page.class);
        voPage.setRecords(MapStructConvertUtil.getRecords(records, tClass));

        return voPage;
    }
}

这样公共方法就被抽取出来了,然后我们去修改一下 service 实现就搞定了

package com.lzl.study.scaffold.studyscaffold.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzl.study.scaffold.studyscaffold.common.mapstruct.MapStructConvertUtil;
import com.lzl.study.scaffold.studyscaffold.common.util.PageUtil;
import com.lzl.study.scaffold.studyscaffold.common.util.QueryWrapperBuildUtil;
import com.lzl.study.scaffold.studyscaffold.user.entity.SysUserEntity;
import com.lzl.study.scaffold.studyscaffold.user.entity.dto.SysUserPageDto;
import com.lzl.study.scaffold.studyscaffold.user.entity.dto.SysUserSaveDto;
import com.lzl.study.scaffold.studyscaffold.user.entity.vo.SysUserPageHomeVo;
import com.lzl.study.scaffold.studyscaffold.user.mapper.SysUserMapper;
import com.lzl.study.scaffold.studyscaffold.user.service.SysUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @ClassName SysUserServiceImpl
 * @Author lizelin
 * @Description 用户管理 serviceImpl
 * @Date 2023-10-09 19:58
 * @Version 1.0
 */
@Service
@Slf4j
@AllArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserEntity> implements SysUserService {

    /**
     * @param sysUserSaveDto
     * @return java.lang.Boolean
     * @Description 通过 dto 新增
     * @author lizelin
     * @date 2023-10-10 0:08
     **/
    @Override
    public Boolean dtoSave(SysUserSaveDto sysUserSaveDto) {
        SysUserEntity entity = MapStructConvertUtil.mapStructConvert(sysUserSaveDto, SysUserEntity.class);
        return save(entity);
    }

    /**
     * @param dto
     * @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.lzl.study.scaffold.studyscaffold.user.entity.vo.SysUserPageVo>
     * @Description 分页查询
     * @author lizelin
     * @date 2023-10-10 17:44
     **/
    @Override
    public Page<SysUserPageHomeVo> dtoPage(SysUserPageDto dto) {
        SysUserEntity entity =  MapStructConvertUtil.mapStructConvert(dto, SysUserEntity.class);
        Page<SysUserEntity> page =  MapStructConvertUtil.mapStructConvert(dto, Page.class);
        page(page, Wrappers.lambdaQuery(entity));
        //转换分页
        return PageUtil.convertPage(page, SysUserPageHomeVo.class);
    }
}

然后我们进行测试

image-20231011071718188

返回结果一切正常

VO 转换问题也就搞定了

然后我们在优化一下

/**
 * @param source 源对象
 * @param tClass 目标 class
 * @return T
 * @Description 将源对象转换为 目标对象
 * @author lizelin
 * @date 2023-10-11 6:37
 **/
public static <T> T mapStructConvert(Object source, Class<T> tClass) {
    Class<?> aClass = source.getClass();
    String sourceName = aClass.getSimpleName();
    String targetName = tClass.getSimpleName();
    //拼接方法名
    StringBuilder builder = StrUtil.builder();
    builder.append("convert");
    builder.append(sourceName);
    builder.append("To");
    builder.append(targetName);
    String me = builder.toString();
    try {
        //反射调用方法
        Method method = mapStructConvert.getClass().getMethod(me, aClass);
        Object invoke = method.invoke(mapStructConvert, source);
        return (T) invoke;
    } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
        e.printStackTrace();

    }
    return null;
}

看这里,每次过来都需要反射去拿他的方法,而实际上这个东西只要你方法名称不变,那么实际上也就意味着你执行的 method 不会变,因为我们之前规定过方法名称格式嘛,所以我们可以做一个缓存对他进行存储,就不需要再次反射拿方法了

首先引入 guava 包

<!-- guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.1-jre</version>
</dependency>

然后在 MapStructConvertUtil 上加一个缓存

package com.lzl.study.scaffold.studyscaffold.common.mapstruct;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName MapStructConvertUtil
 * @Author lizelin
 * @Description MapStruct 转换工具类
 * @Date 2023-10-11 5:53
 * @Version 1.0
 */
public class MapStructConvertUtil {

    private MapStructConvertUtil() {
        throw new IllegalStateException("工具类不允许实例化");
    }

    private static MapStructConvert mapStructConvert;
    /**
     * Method 缓存 避免多次反射
     */
    private static Cache<String, Method> methodCache;

    static {
        methodCache = CacheBuilder.newBuilder()
                //初始容量
                .initialCapacity(2048)
                .maximumSize(2000)
                .build();
        MapStructConvert bean = SpringUtil.getBean(MapStructConvert.class);
        MapStructConvertUtil.mapStructConvert = bean;
    }

    /**
     * @param list   分页数据
     * @param tClass 转换目标类型
     * @return java.util.List<T>
     * @Description 转换 Page 的 records
     * @author lizelin
     * @date 2023-10-11 6:38
     **/
    public static <T, E> List<T> getRecords(List<E> list, Class<T> tClass) {
        Object collect = list.stream().map(item -> mapStructConvert(item, tClass)).collect(Collectors.toList());
        return (List<T>) collect;
    }

    /**
     * @param source 源对象
     * @param tClass 目标 class
     * @return T
     * @Description 将源对象转换为 目标对象
     * @author lizelin
     * @date 2023-10-11 6:37
     **/
    public static <T> T mapStructConvert(Object source, Class<T> tClass) {
        Class<?> aClass = source.getClass();
        String sourceName = aClass.getSimpleName();
        String targetName = tClass.getSimpleName();
        //拼接方法名
        StringBuilder builder = StrUtil.builder();
        builder.append("convert");
        builder.append(sourceName);
        builder.append("To");
        builder.append(targetName);
        String me = builder.toString();
        try {
            Method present = methodCache.getIfPresent(me);
            if (present == null) {
                //反射获取方法
                present = mapStructConvert.getClass().getMethod(me, aClass);
                methodCache.put(me, present);
            }
            Object invoke = present.invoke(mapStructConvert, source);
            return (T) invoke;
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();

        }
        return null;
    }

}

这样也就搞定了

3.1.2、浪费问题

查全量然后展示少数会浪费问题,这个问题的话,实际上就是我们在查询的时候指定查询哪些字段

而这个问题的话,我们可以通过在 生成 QueryWrapper 的时候去调用他的 select 方法来得到指定

那现在问题就来了,能指定那么改如何获取字段呢?

**通过反射的方式获取 VO 的字段,并且设置到 QueryWrapper **

我们来做一个生成 QueryWrapper 的工具类

package com.lzl.study.scaffold.studyscaffold.common.util;

import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import java.lang.reflect.Field;

/**
 * @ClassName QueryWrapperBuildUtil
 * @Author lizelin
 * @Description 查询包装 构建工具类
 * @Date 2023-10-10 18:33
 * @Version 1.0
 */
public class QueryWrapperBuildUtil {

    /**
     * 缓存 避免多次反射
     */
    private static Cache<Class, String[]> tableFideCache;

    static {
        tableFideCache = CacheBuilder.newBuilder()
                //初始容量
                .initialCapacity(2048)
                .maximumSize(2000)
                .build();
    }

    private QueryWrapperBuildUtil() {
        throw new IllegalStateException("工具类不允许实例化");
    }

    /**
     * @return com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
     * @Description 获取 QueryWrapper
     * @author lizelin
     * @date 2023-10-10 17:52
     **/
    public static <T> QueryWrapper<T> buildQueryWrapper(T obj) {
        return Wrappers.query(obj);
    }

    /**
     * @param obj 期望的条件实体
     * @return com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<T>
     * @Description 获取 LambdaQueryWrapper
     * @author lizelin
     * @date 2023-10-12 18:19
     **/
    public static <T> LambdaQueryWrapper<T> buildLambdaQueryWrapper(T obj) {
        return Wrappers.lambdaQuery(obj);
    }

    /**
     * @param obj     期望的条件实体
     * @param voClass 希望查的字段
     * @return com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<T>
     * @Description 获取指定 vo 字段的 QueryWrapper
     * @author lizelin
     * @date 2023-10-12 18:19
     **/
    public static <T> LambdaQueryWrapper<T> buildLambdaQueryWrapper(T obj, Class<?> voClass) {
        QueryWrapper<T> query = Wrappers.query(obj);

        String[] voTableFide = tableFideCache.getIfPresent(voClass);
        if (voTableFide == null) {
            voTableFide = getVoTableFide(voClass);
            tableFideCache.put(voClass, voTableFide);
        }

        query.select(voTableFide);
        return query.lambda();
    }

    /**
     * @param voClass vo
     * @return java.lang.String[]
     * @Description 获取 vo 存在的字段
     * @author lizelin
     * @date 2023-10-12 18:18
     **/
    private static String[] getVoTableFide(Class<?> voClass) {
        Field[] fields = voClass.getDeclaredFields();
        String[] fieldsStr = new String[fields.length];
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            String fieldName = field.getName();
            String underlineCase = CharSequenceUtil.toUnderlineCase(fieldName);
            fieldsStr[i] = underlineCase;
        }
        return fieldsStr;
    }
}

然后去改造一下实现类

package com.lzl.study.scaffold.studyscaffold.user.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzl.study.scaffold.studyscaffold.common.mapstruct.MapStructConvertUtil;
import com.lzl.study.scaffold.studyscaffold.common.util.PageUtil;
import com.lzl.study.scaffold.studyscaffold.common.util.QueryWrapperBuildUtil;
import com.lzl.study.scaffold.studyscaffold.user.entity.SysUserEntity;
import com.lzl.study.scaffold.studyscaffold.user.entity.dto.SysUserPageDto;
import com.lzl.study.scaffold.studyscaffold.user.entity.dto.SysUserSaveDto;
import com.lzl.study.scaffold.studyscaffold.user.entity.vo.SysUserPageHomeVo;
import com.lzl.study.scaffold.studyscaffold.user.mapper.SysUserMapper;
import com.lzl.study.scaffold.studyscaffold.user.service.SysUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @ClassName SysUserServiceImpl
 * @Author lizelin
 * @Description 用户管理 serviceImpl
 * @Date 2023-10-09 19:58
 * @Version 1.0
 */
@Service
@Slf4j
@AllArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserEntity> implements SysUserService {

    /**
     * @param sysUserSaveDto
     * @return java.lang.Boolean
     * @Description 通过 dto 新增
     * @author lizelin
     * @date 2023-10-10 0:08
     **/
    @Override
    public Boolean dtoSave(SysUserSaveDto sysUserSaveDto) {
        SysUserEntity entity = MapStructConvertUtil.mapStructConvert(sysUserSaveDto, SysUserEntity.class);
        return save(entity);
    }

    /**
     * @param dto
     * @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.lzl.study.scaffold.studyscaffold.user.entity.vo.SysUserPageVo>
     * @Description 分页查询
     * @author lizelin
     * @date 2023-10-10 17:44
     **/
    @Override
    public Page<SysUserPageHomeVo> dtoPage(SysUserPageDto dto) {
        SysUserEntity entity = MapStructConvertUtil.mapStructConvert(dto, SysUserEntity.class);
        Page<SysUserEntity> page = MapStructConvertUtil.mapStructConvert(dto, Page.class);
        page(page, QueryWrapperBuildUtil.buildLambdaQueryWrapper(entity, SysUserPageHomeVo.class));
        //转换分页
        return PageUtil.convertPage(page, SysUserPageHomeVo.class);
    }
}

然后看一下效果如何

image-20231012183411025

可以看到是生效了的

但是这个时候就发现了一个小问题,ID 没有出来,反射的时候取字段的话只能取到当前类的字段,所以我们得优化一下方法,将父类的字段也给取出来

package com.lzl.study.scaffold.studyscaffold.common.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName QueryWrapperBuildUtil
 * @Author lizelin
 * @Description 查询包装 构建工具类
 * @Date 2023-10-10 18:33
 * @Version 1.0
 */
public class QueryWrapperBuildUtil {

    /**
     * 缓存 避免多次反射
     */
    private static Cache<Class<?>, String[]> tableFideCache;

    static {
        tableFideCache = CacheBuilder.newBuilder()
                //初始容量
                .initialCapacity(2048)
                .maximumSize(2000)
                .build();
    }

    private QueryWrapperBuildUtil() {
        throw new IllegalStateException("工具类不允许实例化");
    }

    /**
     * @return com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
     * @Description 获取 QueryWrapper
     * @author lizelin
     * @date 2023-10-10 17:52
     **/
    public static <T> QueryWrapper<T> buildQueryWrapper(T obj) {
        return Wrappers.query(obj);
    }

    /**
     * @param obj 期望的条件实体
     * @return com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<T>
     * @Description 获取 LambdaQueryWrapper
     * @author lizelin
     * @date 2023-10-12 18:19
     **/
    public static <T> LambdaQueryWrapper<T> buildLambdaQueryWrapper(T obj) {
        return Wrappers.lambdaQuery(obj);
    }

    /**
     * @param obj     期望的条件实体
     * @param voClass 希望查的字段
     * @return com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<T>
     * @Description 获取指定 vo 字段的 QueryWrapper
     * @author lizelin
     * @date 2023-10-12 18:19
     **/
    public static <T> LambdaQueryWrapper<T> buildLambdaQueryWrapper(T obj, Class<?> voClass) {
        QueryWrapper<T> query = Wrappers.query(obj);

        String[] voTableFide = tableFideCache.getIfPresent(voClass);
        if (voTableFide == null) {
            voTableFide = getVoTableFide(voClass);
            tableFideCache.put(voClass, voTableFide);
        }

        query.select(voTableFide);
        return query.lambda();
    }

    /**
     * @param voClass vo
     * @return java.lang.String[]
     * @Description 获取 vo 存在的字段
     * @author lizelin
     * @date 2023-10-12 18:18
     **/
    private static String[] getVoTableFide(Class<?> voClass) {
        List<Field> fields = new ArrayList();
        getTableFide(voClass, fields);

        String[] fieldsStr = new String[fields.size()];
        for (int i = 0; i < fields.size(); i++) {
            Field field = fields.get(i);
            String fieldName = field.getName();
            String underlineCase = CharSequenceUtil.toUnderlineCase(fieldName);
            fieldsStr[i] = underlineCase;
        }
        return fieldsStr;
    }

    /**
     * @param aClass
     * @param fields
     * @return java.lang.String[]
     * @Description 递归 取得父类字段
     * @author lizelin
     * @date 2023-10-12 18:44
     **/
    private static void getTableFide(Class<?> aClass, List<Field> fields) {
        Field[] aClassDeclaredFields = aClass.getDeclaredFields();
        //排除掉 序列化版本 ID
        for (Field item : aClassDeclaredFields) {
            if (!StrUtil.equals("serialVersionUID", item.getName())) {
                fields.add(item);
            }
        }
        Class<?> superclass = aClass.getSuperclass();
        if (superclass != Object.class) {
            getTableFide(superclass, fields);
        }
    }


我们新增了一个 getTableFide 方法,通过递归的方式,取出来父类存在的字段,这样就解决了问题

image-20231012205711907

这里就可以看到效果了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值