优雅转换对象MapstructPlus跟优雅分页查询

315 阅读3分钟

优雅转换对象MapstructPlus跟优雅分页查询

MapstructUtils的应用

使用场景为对象vo bo po等的优雅转换

用到的插件

mapstruct.plus/introductio…

集成了一个工具类

package com.xiaou.common.utils;
​
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import io.github.linpeilie.Converter;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
​
import java.util.List;
import java.util.Map;
​
/**
 * Mapstruct 工具类
 * <p>参考文档:<a href="https://mapstruct.plus/introduction/quick-start.html">mapstruct-plus</a></p>
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MapstructUtils {
​
    private final static Converter CONVERTER = SpringUtils.getBean(Converter.class);
​
    /**
     * 将 T 类型对象,转换为 desc 类型的对象并返回
     *
     * @param source 数据来源实体
     * @param desc   描述对象 转换后的对象
     * @return desc
     */
    public static <T, V> V convert(T source, Class<V> desc) {
        if (ObjectUtil.isNull(source)) {
            return null;
        }
        if (ObjectUtil.isNull(desc)) {
            return null;
        }
        return CONVERTER.convert(source, desc);
    }
​
    /**
     * 将 T 类型对象,按照配置的映射字段规则,给 desc 类型的对象赋值并返回 desc 对象
     *
     * @param source 数据来源实体
     * @param desc   转换后的对象
     * @return desc
     */
    public static <T, V> V convert(T source, V desc) {
        if (ObjectUtil.isNull(source)) {
            return null;
        }
        if (ObjectUtil.isNull(desc)) {
            return null;
        }
        return CONVERTER.convert(source, desc);
    }
​
    /**
     * 将 T 类型的集合,转换为 desc 类型的集合并返回
     *
     * @param sourceList 数据来源实体列表
     * @param desc       描述对象 转换后的对象
     * @return desc
     */
    public static <T, V> List<V> convert(List<T> sourceList, Class<V> desc) {
        if (ObjectUtil.isNull(sourceList)) {
            return null;
        }
        if (CollUtil.isEmpty(sourceList)) {
            return CollUtil.newArrayList();
        }
        return CONVERTER.convert(sourceList, desc);
    }
​
    /**
     * 将 Map 转换为 beanClass 类型的集合并返回
     *
     * @param map       数据来源
     * @param beanClass bean类
     * @return bean对象
     */
    public static <T> T convert(Map<String, Object> map, Class<T> beanClass) {
        if (MapUtil.isEmpty(map)) {
            return null;
        }
        if (ObjectUtil.isNull(beanClass)) {
            return null;
        }
        return CONVERTER.convert(map, beanClass);
    }
​
}

只需要引入

<dependency>
    <groupId>io.github.linpeilie</groupId>
    <artifactId>mapstruct-plus-spring-boot-starter</artifactId>
</dependency>

具体转换方法。

实体类就是跟sq对应的类一般是不用动的。

例如

​
@TableName(value = "u_student_user")
@Data
public class StudentUser {
    /**
     * 主键ID
     */
    @TableId
    private Long id;
​
    /**
     * 学号
     */
    private String studentNumber;
​
    /**
     * 姓名
     */
    private String name;
​
    /**
     * 密码
     */
    private String password;
​
    /**
     * 创建时间
     */
    private Date createTime;
​
    /**
     * 更新时间
     */
    private Date updateTime;
​
    /**
     * 头像
     */
    private String avatarUrl;
​
​
    /**
     * 邮箱
     */
    private String email;
}

之后我们在Bo

@Data
@AutoMapper(target = StudentUser.class)
public class StudentUserBo {
​
    /**
     * 学号
     */
    @NotBlank(message = "学号不为空")
    private String studentNumber;
​
​
    /**
     * 密码
     */
    @NotBlank(message = "密码不为空")
    private String password;
​
}

加上@AutoMapper注解。

之后我们调用MapstructUtils.convert这个方法,就可以直接进行转换为vo对象进行返回。

@Override
public R<StudentUserVo> getLogin(String currentStudentId) {
    //根据id查询学生信息
    StudentUser studentUser = baseMapper.selectById(currentStudentId);
    StudentUserVo studentUserVo = MapstructUtils.convert(studentUser, StudentUserVo.class);
    return R.ok(studentUserVo);
}

分页的应用

一般是返回类为

package com.xiaou.common.page;
​
import lombok.Getter;
​
import java.util.List;
​
/**
 * 分页响应数据格式封装
 */
@Getter
public class PageRespDto<T> {
​
    /**
     * 页码
     */
    private final long pageNum;
​
    /**
     * 每页大小
     */
    private final long pageSize;
​
    /**
     * 总记录数
     */
    private final long total;
​
    /**
     * 分页数据集
     */
    private final List<? extends T> list;
​
    /**
     * 该构造函数用于通用分页查询的场景 接收普通分页数据和普通集合
     */
    public PageRespDto(long pageNum, long pageSize, long total, List<T> list) {
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.total = total;
        this.list = list;
    }
​
    public static <T> PageRespDto<T> of(long pageNum, long pageSize, long total, List<T> list) {
        return new PageRespDto<>(pageNum, pageSize, total, list);
    }
​
    /**
     * 获取分页数
     */
    public long getPages() {
        if (this.pageSize == 0L) {
            return 0L;
        } else {
            long pages = this.total / this.pageSize;
            if (this.total % this.pageSize != 0L) {
                ++pages;
            }
            return pages;
        }
    }
}

前端需要传的是

package com.xiaou.common.page;
​
import lombok.Data;
​
@Data
public class PageReqDto {
​
    /**
     * 请求页码,默认第 1 页
     */
    private int pageNum = 1;
​
    /**
     * 每页大小,默认每页 10 条
     */
    private int pageSize = 10;
​
    /**
     * 是否查询所有,默认不查所有 为 true 时,pageNum 和 pageSize 无效
     */
    private boolean fetchAll = false;
​
    private String sortField; // 排序字段
​
    private Boolean desc = true; // 是否降序,默认 true(倒序)
​
}

之后service

@Override
public R<PageRespDto<PlaceCategoryVO>> list(PageReqDto dto) {
    IPage<PlaceCategory> page = placeCategoryMapper.selectPage(
            new Page<>(dto.getPageNum(), dto.getPageSize()),
            new QueryWrapper<>()
    );
​
    List<PlaceCategoryVO> voList = MapstructUtils.convert(page.getRecords(), PlaceCategoryVO.class);
​
    return R.ok(PageRespDto.of(dto.getPageNum(), dto.getPageSize(), page.getTotal(), voList));
}

这里的排序字段。

可以选择添加与否

然后调用排序

public class QueryWrapperUtil {
​
    /**
     * 给 QueryWrapper 添加排序(布尔控制升降序)
     */
    public static <T> void applySorting(QueryWrapper<T> wrapper, PageReqDto dto, List<String> validFields) {
        String field = dto.getSortField();
        Boolean desc = dto.getDesc();
​
        if (StrUtil.isNotBlank(field) && validFields.contains(field)) {
            wrapper.orderBy(true, desc == null || !desc, field); // true:是否添加排序,false:升序
        }
    }
}
QueryWrapper<SysOperLog> queryWrapper = new QueryWrapper<>();
QueryWrapperUtil.applySorting(queryWrapper, dto, List.of(dto.getSortField()));