自定义EasyCode模板生成CRUD

发布于:2025-02-10 ⋅ 阅读:(165) ⋅ 点赞:(0)

1.生成步骤

1.定义全局逻辑删除字段名称以及删除值和未删除值

CleanShot 2024-10-11 at 18.33.08@2x

2.简单三层架构模板
1.概览

CleanShot 2024-10-11 at 18.33.54@2x

2.Req.java
## 引入宏定义
$!{define.vm}

## 设置保存名称与保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "Req.java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/entity/req"))

## 拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

## 包声明和导入
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.entity.req;
#end

import $!{tableInfo.savePackageName}.entity.page.PageInfo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
## 检查是否包含 Date 类型的字段
#set($containsDate = false)
#foreach($column in $tableInfo.fullColumn)
    #if($tool.getClsNameByFullName($column.type) == "Date")
        #set($containsDate = true)
        #break
    #end
#end
## 如果包含 Date 类型的字段,导入 java.util.Date
#if($containsDate)
import java.util.Date;
#end

/**
 * $!{tableInfo.comment}($!{tableInfo.name})Req实体类:接受前端请求
 *
 * @author $!author
 * @since $!time.currTime()
 */
@Data
@Accessors(chain = true) // 支持链式调用
public class $!{tableInfo.name}Req extends PageInfo implements Serializable {

    private static final long serialVersionUID = 1L;

#foreach($column in $tableInfo.fullColumn)
    ## 添加字段注释
    #if($column.comment)/**
     * $column.comment
     */#end
    private $!{tool.getClsNameByFullName($column.type)} $!{column.name};

#end
}
3.Vo.java
## 引入宏定义
$!{define.vm}

## 设置保存名称与保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "Vo.java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/entity/vo"))

## 拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

## 包声明和导入
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.entity.vo;
#end

import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
## 检查是否包含 Date 类型的字段
#set($containsDate = false)
#foreach($column in $tableInfo.fullColumn)
    #if($tool.getClsNameByFullName($column.type) == "Date")
        #set($containsDate = true)
        #break
    #end
#end
## 如果包含 Date 类型的字段,导入 java.util.Date
#if($containsDate)
import java.util.Date;
#end

/**
 * $!{tableInfo.comment}($!{tableInfo.name})VO实体类:封装后端给前端的响应
 *
 * @author $!author
 * @since $!time.currTime()
 */
@Data
@Accessors(chain = true) // 支持链式调用
public class $!{tableInfo.name}Vo implements Serializable {

    private static final long serialVersionUID = 1L;

#foreach($column in $tableInfo.fullColumn)
    ## 添加字段注释
    #if($column.comment)/**
     * $column.comment
     */#end
    private $!{tool.getClsNameByFullName($column.type)} $!{column.name};

#end
}
4.Po.java
## 引入宏定义
$!{define.vm}

## 设置保存名称与保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "Po.java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/entity/po"))

## 拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

## 包声明和导入
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.entity.po;
#end

import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
## 检查是否包含 Date 类型的字段
#set($containsDate = false)
#foreach($column in $tableInfo.fullColumn)
    #if($tool.getClsNameByFullName($column.type) == "Date")
        #set($containsDate = true)
        #break
    #end
#end
## 如果包含 Date 类型的字段,导入 java.util.Date
#if($containsDate)
import java.util.Date;
#end

/**
 * $!{tableInfo.comment}($!{tableInfo.name})PO实体类
 *
 * @author $!author
 * @since $!time.currTime()
 */
@Data
@Accessors(chain = true) // 支持链式调用
public class $!{tableInfo.name}Po implements Serializable {

    private static final long serialVersionUID = 1L;

#foreach($column in $tableInfo.fullColumn)
    ## 添加字段注释
    #if($column.comment)/**
     * $column.comment
     */#end
    private $!{tool.getClsNameByFullName($column.type)} $!{column.name};

#end
}
5.Mapper.java
## 设置保存名称与保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "Mapper.java"))
$!callback.setSavePath($tool.append($modulePath, "/src/main/java/$!{tableInfo.savePackageName.replace('.','/')}/mapper"))
##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

package $!{tableInfo.savePackageName}.mapper;

import $!{tableInfo.savePackageName}.entity.po.$!{tableInfo.name}Po;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * ($!{tableInfo.name})表数据库访问层
 *
 * @author $!{author}
 * @since $!{time.currTime('yyyy-MM-dd HH:mm:ss')}
 */
public interface $!{tableInfo.name}Mapper {

    /**
     * 根据主键查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    $!{tableInfo.name}Po queryById(@Param("id") $!{pk.shortType} id);

    /**
     * 分页查询
     *
     * @param po 查询条件
     * @param offset 偏移量:计算公式 (pageNo - 1) * pageSize
     * @param pageSize 页面大小
     * @return 对象列表
     */
    List<$!{tableInfo.name}Po> queryPage(@Param("po") $!{tableInfo.name}Po po, @Param("offset") Integer offset, @Param("pageSize") Integer pageSize);

    /**
     * 根据条件查询记录
     *
     * @param po 查询条件
     * @return 对象列表
     */
    List<$!{tableInfo.name}Po> queryAllByLimit(@Param("po") $!{tableInfo.name}Po po);

    /**
     * 统计总行数
     *
     * @param po 查询条件
     * @return 总行数
     */
    Integer count(@Param("po") $!{tableInfo.name}Po po);

    /**
     * 新增数据
     *
     * @param po 实例对象(会封装新增的id)
     * @return 影响行数
     */
    int insert($!{tableInfo.name}Po po);

    /**
     * 批量新增数据(MyBatis原生foreach方法)
     *
     * @param entities 实例对象列表(会封装新增的id)
     * @return 影响行数
     */
    int insertBatch(@Param("entities") List<$!{tableInfo.name}Po> entities);

    /**
     * 批量新增或按主键更新数据(MyBatis原生foreach方法)
     *
     * @param entities 实例对象列表
     * @return 影响行数
     * @throws org.springframework.jdbc.BadSqlGrammarException 入参是空List的时候会抛SQL语句错误的异常,请自行校验入参
     */
    int insertOrUpdateBatch(@Param("entities") List<$!{tableInfo.name}Po> entities);

    /**
     * 根据主键修改数据
     *
     * @param po 实例对象
     * @return 影响行数
     */
    int updateById($!{tableInfo.name}Po po);

    /**
     * 根据主键逻辑删除数据
     *
     * @param id 主键
     * @return 影响行数
     */
    int logicDeleteById(@Param("id") $!{pk.shortType} id);

    /**
     * 根据主键批量逻辑删除数据
     *
     * @param ids 主键列表
     * @return 影响行数
     */
    int logicDeleteBatchById(@Param("list") List<$!{pk.shortType}> ids);
}
6.Mapper.xml
##定义全局逻辑删除字段名称
#set($deleteColumnName = "is_deleted")
##定义全局逻辑删除字段的删除值和未删除值
#set($deleteColumnValue = 1)
#set($notDeletedColumnValue = 0)

##引入mybatis支持
$!{mybatisSupport.vm}

##设置保存名称与保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "Mapper.xml"))
$!callback.setSavePath($tool.append($modulePath, "/src/main/resources/mapper"))

##拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="$!{tableInfo.savePackageName}.mapper.$!{tableInfo.name}Mapper">
    <resultMap type="$!{tableInfo.savePackageName}.entity.po.$!{tableInfo.name}Po" id="$!{tableInfo.name}Map">
        <id property="$!pk.name" column="$!pk.obj.name"/>
#foreach($column in $tableInfo.fullColumn)
    #if($column.name != $pk.name)
        <result property="$!column.name" column="$!column.obj.name"/>
    #end
#end
    </resultMap>

    <!--根据主键查询一条记录-->
    <select id="queryById" resultMap="$!{tableInfo.name}Map">
        select #allSqlColumn()
        from $!{tableInfo.obj.name}
        where $!pk.obj.name = #{$!pk.name}
        and $!deleteColumnName = $notDeletedColumnValue
    </select>

    <!--分页查询指定行数据-->
    <select id="queryPage" resultMap="$!{tableInfo.name}Map">
        select #allSqlColumn()
        from $!{tableInfo.obj.name}
        <where>
#foreach($column in $tableInfo.fullColumn)
            <if test="po.$!column.name != null#if($column.type.equals('java.lang.String')) and po.$!column.name != ''#end">
                and $!column.obj.name = #{po.$!column.name}
            </if>
#end
            and $!deleteColumnName = $notDeletedColumnValue
        </where>
        limit #{offset}, #{pageSize}
    </select>

    <!--根据条件查询记录-->
    <select id="queryAllByLimit" resultMap="$!{tableInfo.name}Map">
        select #allSqlColumn()
        from $!{tableInfo.obj.name}
        <where>
#foreach($column in $tableInfo.fullColumn)
            <if test="po.$!column.name != null#if($column.type.equals('java.lang.String')) and po.$!column.name != ''#end">
                and $!column.obj.name = #{po.$!column.name}
            </if>
#end
            and $!deleteColumnName = $notDeletedColumnValue
        </where>
    </select>

    <!--根据条件统计总行数-->
    <select id="count" resultType="java.lang.Integer">
        select count(1)
        from $!{tableInfo.obj.name}
        <where>
#foreach($column in $tableInfo.fullColumn)
            <if test="po.$!column.name != null#if($column.type.equals('java.lang.String')) and po.$!column.name != ''#end">
                and $!column.obj.name = #{po.$!column.name}
            </if>
#end
            and $!deleteColumnName = $notDeletedColumnValue
        </where>
    </select>

    <!--新增一条记录-->
    <insert id="insert" keyProperty="$!pk.name" useGeneratedKeys="true">
        insert into $!{tableInfo.obj.name}(#foreach($column in $tableInfo.otherColumn)$!column.obj.name#if($foreach.hasNext), #end#end)
        values (#foreach($column in $tableInfo.otherColumn)#{$!column.name}#if($foreach.hasNext), #end#end)
    </insert>

    <!--批量新增多条记录-->
    <insert id="insertBatch" keyProperty="$!pk.name" useGeneratedKeys="true">
        insert into $!{tableInfo.obj.name}(#foreach($column in $tableInfo.otherColumn)$!column.obj.name#if($foreach.hasNext), #end#end)
        values
        <foreach collection="entities" item="entity" separator=",">
            (#foreach($column in $tableInfo.otherColumn)#{entity.$!column.name}#if($foreach.hasNext), #end#end)
        </foreach>
    </insert>

    <!--插入记录,如果主键冲突,则变为更新记录-->
    <insert id="insertOrUpdateBatch" keyProperty="$!pk.name" useGeneratedKeys="true">
        insert into $!{tableInfo.obj.name}(id, #foreach($column in $tableInfo.otherColumn)$!column.obj.name#if($foreach.hasNext), #end#end)
        values
        <foreach collection="entities" item="entity" separator=",">
            (#{entity.id}, #foreach($column in $tableInfo.otherColumn)#{entity.$!column.name}#if($foreach.hasNext), #end#end)
        </foreach>
        on duplicate key update
#foreach($column in $tableInfo.otherColumn)
            $!column.obj.name = values($!column.obj.name)#if($foreach.hasNext),#end
#end
    </insert>

    <!--根据主键修改数据-->
    <update id="updateById">
        update $!{tableInfo.obj.name}
        <set>
#foreach($column in $tableInfo.otherColumn)
            <if test="$!column.name != null#if($column.type.equals('java.lang.String')) and $!column.name != ''#end">
                $!column.obj.name = #{$!column.name},
            </if>
#end
        </set>
        where $!pk.obj.name = #{$!pk.name}
        and $!deleteColumnName = $notDeletedColumnValue
    </update>

    <!--根据主键逻辑删除单个记录-->
    <update id="logicDeleteById">
        update $!{tableInfo.obj.name}
        set $!deleteColumnName = $deleteColumnValue
        where $!pk.obj.name = #{$!pk.name}
        and $!deleteColumnName = $notDeletedColumnValue
    </update>

    <!--根据主键批量逻辑删除记录-->
    <update id="logicDeleteBatchById">
        update $!{tableInfo.obj.name}
        set $!deleteColumnName = $deleteColumnValue
        where $!pk.obj.name in
        <foreach collection="list" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
        and $!deleteColumnName = $notDeletedColumnValue
    </update>
</mapper>
7.Service.java
## 引入宏定义
$!{define.vm}

## 设置保存名称与保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "Service.java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/service"))

## 拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

## 包声明和导入
package $!{tableInfo.savePackageName}.service;

import $!{tableInfo.savePackageName}.entity.page.PageResult;
import $!{tableInfo.savePackageName}.entity.req.$!{tableInfo.name}Req;
import $!{tableInfo.savePackageName}.entity.vo.$!{tableInfo.name}Vo;

/**
 * $!{tableInfo.comment}($!{tableInfo.name}) service 接口
 *
 * @author sun
 * @since $!time.currTime("yyyy-MM-dd HH:mm:ss")
 */
public interface $!{tableInfo.name}Service {

    /**
     * 分页查询
     *
     * @param req 筛选条件
     * @return 查询结果
     */
    PageResult<$!{tableInfo.name}Vo> queryByPage($!{tableInfo.name}Req req);

}
8.ServiceImpl.java
## 引入宏定义
$!{define.vm}

## 设置保存名称与保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "ServiceImpl.java"))
$!callback.setSavePath($tool.append($!{tableInfo.savePath}, "/service/impl"))

## 拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

## 包声明和导入
package $!{tableInfo.savePackageName}.service.impl;

import $!{tableInfo.savePackageName}.entity.page.PageResult;
import $!{tableInfo.savePackageName}.entity.page.SunPageHelper;
import $!{tableInfo.savePackageName}.entity.po.$!{tableInfo.name}Po;
import $!{tableInfo.savePackageName}.entity.req.$!{tableInfo.name}Req;
import $!{tableInfo.savePackageName}.entity.vo.$!{tableInfo.name}Vo;
import $!{tableInfo.savePackageName}.mapper.$!{tableInfo.name}Mapper;
import $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;

/**
 * $!{tableInfo.comment}($!{tableInfo.name})service实现类
 *
 * @author sun
 * @since $!time.currTime("yyyy-MM-dd HH:mm:ss")
 */
@Service("$!tool.firstLowerCase($!{tableInfo.name})Service")
public class $!{tableInfo.name}ServiceImpl implements $!{tableInfo.name}Service {

    @Resource
    private $!{tableInfo.name}Mapper $!tool.firstLowerCase($!{tableInfo.name})Mapper;

    /**
     * 分页查询
     *
     * @param $!tool.firstLowerCase($!{tableInfo.name})Req 筛选条件,需要携带pageNo和pageSize以及查询条件
     * @return 分页结果
     */
    @Override
    public PageResult<$!{tableInfo.name}Vo> queryByPage($!{tableInfo.name}Req $!tool.firstLowerCase($!{tableInfo.name})Req) {
        // 1.将req转换为po
        $!{tableInfo.name}Po $!tool.firstLowerCase($!{tableInfo.name})Po = convertReqToPo($!tool.firstLowerCase($!{tableInfo.name})Req);
        // 2.使用 SunPageHelper 执行分页操作
        PageResult<$!{tableInfo.name}Po> paginate = SunPageHelper.paginate($!tool.firstLowerCase($!{tableInfo.name})Req.getPageNo(), $!tool.firstLowerCase($!{tableInfo.name})Req.getPageSize(),
                () -> $!tool.firstLowerCase($!{tableInfo.name})Mapper.count($!tool.firstLowerCase($!{tableInfo.name})Po),
                (offset, size) -> $!tool.firstLowerCase($!{tableInfo.name})Mapper.queryPage($!tool.firstLowerCase($!{tableInfo.name})Po, offset, size)
        );
        // 3.将poList转换为voList
        List<$!{tableInfo.name}Vo> $!tool.firstLowerCase($!{tableInfo.name})VoList = convertPoListToVoList(paginate.getResult());
        PageResult<$!{tableInfo.name}Vo> $!tool.firstLowerCase($!{tableInfo.name})VoPageResult = new PageResult.Builder<$!{tableInfo.name}Vo>()
                .pageNo(paginate.getPageNo())
                .pageSize(paginate.getPageSize())
                .total(paginate.getTotal())
                .result($!tool.firstLowerCase($!{tableInfo.name})VoList)
                .build();
        return $!tool.firstLowerCase($!{tableInfo.name})VoPageResult;
    }

    // ============================== 实现转换 ==============================
    private List<$!{tableInfo.name}Vo> convertPoListToVoList(List<$!{tableInfo.name}Po> result) {
        // 自定义转换逻辑
        return null;
    }

    private $!{tableInfo.name}Po convertReqToPo($!{tableInfo.name}Req $!tool.firstLowerCase($!{tableInfo.name})Req) {
        // 自定义转换逻辑
        return null;
    }
    // ============================== 实现转换 ==============================

}
9.Controller.java
## 引入宏定义
$!{define.vm}

## 设置保存名称与保存位置
$!callback.setFileName($tool.append($!{tableInfo.name}, "Controller.java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/controller"))

## 拿到主键
#if(!$tableInfo.pkColumn.isEmpty())
    #set($pk = $tableInfo.pkColumn.get(0))
#end

## 包声明和导入
package $!{tableInfo.savePackageName}.controller;

import $!{tableInfo.savePackageName}.entity.page.PageResult;
import $!{tableInfo.savePackageName}.entity.req.$!{tableInfo.name}Req;
import $!{tableInfo.savePackageName}.entity.vo.$!{tableInfo.name}Vo;
import $!{tableInfo.savePackageName}.response.Result;
import $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * $!{tableInfo.comment}($!{tableInfo.name})控制层
 *
 * @author sun
 * @since $!time.currTime("yyyy-MM-dd HH:mm:ss")
 */
@RestController
@RequestMapping("/$tool.hump2Underline($tool.firstLowerCase($tableInfo.name)).replace('_', '/')")
@Slf4j
public class $!{tableInfo.name}Controller {
    /**
     * 服务对象
     */
    @Resource
    private $!{tableInfo.name}Service $!tool.firstLowerCase($tableInfo.name)Service;

    /**
     * 分页查询数据
     *
     * @param req 筛选条件
     * @return 查询结果
     */
    @GetMapping("/queryPage")
    public Result<PageResult<$!{tableInfo.name}Vo>> queryByPage(@RequestBody $!{tableInfo.name}Req req) {
        // ============================== Preconditions 参数校验 ==============================

        // ============================== Preconditions 参数校验 ==============================
        // 调用service层
        PageResult<$!{tableInfo.name}Vo> $!tool.firstLowerCase($tableInfo.name)VoPageResult = this.$!tool.firstLowerCase($tableInfo.name)Service.queryByPage(req);
        return Result.ok($!tool.firstLowerCase($tableInfo.name)VoPageResult);
    }
}
3.通用配置生成模板
1.概览

CleanShot 2024-10-11 at 18.38.21@2x

2.PageInfo.java
##定义初始变量
#set($className = "PageInfo")
##设置回调
$!callback.setFileName($className + ".java")
$!callback.setSavePath($tool.append($tableInfo.savePath, "/entity/page"))
##包名
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.entity.page;#end

import java.util.Objects;

/**
 * Description: 分页请求的入参
 * @Author $!author
 * @Create $!time.currTime()
 * @Version 1.1
 */
public class $className {

    private Integer pageNo = 1;
    private Integer pageSize = 20;

    public Integer getPageNo() {
        return (pageNo == null || pageNo < 1) ? 1 : pageNo;
    }

    public Integer getPageSize() {
        return (pageSize == null || pageSize < 1) ? 20 : pageSize;
    }

    public $className setPageNo(Integer pageNo) {
        this.pageNo = pageNo;
        return this;
    }

    public $className setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
        return this;
    }

    @Override
    public int hashCode() {
        return Objects.hash(pageNo, pageSize);
    }

    @Override
    public String toString() {
        return "$className{" +
                "pageNo=" + pageNo +
                ", pageSize=" + pageSize +
                '}';
    }
}
3.PageResult.java
##定义初始变量
#set($className = "PageResult")
##设置回调
$!callback.setFileName($className + ".java")
$!callback.setSavePath($tool.append($tableInfo.savePath, "/entity/page"))
##包名
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.entity.page;#end

import java.util.Collections;
import java.util.List;

import static java.util.Objects.requireNonNull;

/**
 * Description: 分页返回的实体
 * @Author $!author
 * @Create $!time.currTime()
 * @Version 1.1
 */
public class $className<T> {

    // 当前页码,默认为1
    private Integer pageNo = 1;

    // 每页显示的记录数,默认为20
    private Integer pageSize = 20;

    // 总记录条数
    private Integer total = 0;

    // 总页数
    private Integer totalPages = 0;

    // 当前页的记录列表
    private List<T> result = Collections.emptyList();

    // 表示当前页是从分页查询结果的第几条记录开始,下标从1开始
    private Integer start = 1;

    // 表示当前页是从分页查询结果的第几条记录结束,下标从1开始
    private Integer end = 0;

    // 私有构造函数,使用Builder创建实例
    private $className(Builder<T> builder) {
        this.pageNo = builder.pageNo;
        this.pageSize = builder.pageSize;
        this.total = builder.total;
        this.result = builder.result;
        calculateTotalPages();
        calculateStartAndEnd();
    }

    // Builder 模式实现
    public static class Builder<T> {
        private Integer pageNo = 1;
        private Integer pageSize = 20;
        private Integer total = 0;
        private List<T> result = Collections.emptyList();

        public Builder<T> pageNo(Integer pageNo) {
            this.pageNo = requireNonNull(pageNo, "Page number cannot be null");
            return this;
        }

        public Builder<T> pageSize(Integer pageSize) {
            this.pageSize = requireNonNull(pageSize, "Page size cannot be null");
            return this;
        }

        public Builder<T> total(Integer total) {
            this.total = requireNonNull(total, "Total count cannot be null");
            return this;
        }

        public Builder<T> result(List<T> result) {
            this.result = requireNonNull(result, "Result list cannot be null");
            return this;
        }

        public $className<T> build() {
            return new $className<>(this);
        }
    }

    // 计算总页数
    private void calculateTotalPages() {
        if (this.pageSize > 0) {
            this.totalPages = (this.total / this.pageSize) + (this.total % this.pageSize == 0 ? 0 : 1);
        } else {
            this.totalPages = 0;
        }
    }

    // 计算起始和结束位置
    private void calculateStartAndEnd() {
        if (this.pageSize > 0) {
            this.start = (this.pageNo - 1) * this.pageSize + 1;
            this.end = Math.min(this.pageNo * this.pageSize, this.total);
        } else {
            this.start = 1;
            this.end = this.total;
        }
    }

    // 获取当前页的起始位置
    public Integer getStart() {
        return start;
    }

    // 获取每页记录数
    public Integer getPageSize() {
        return pageSize;
    }

    // 获取当前页码
    public Integer getPageNo() {
        return pageNo;
    }

    // 获取总记录条数
    public Integer getTotal() {
        return total;
    }

    // 获取总页数
    public Integer getTotalPages() {
        return totalPages;
    }

    // 获取当前页的记录列表
    public List<T> getResult() {
        return result;
    }

    // 获取当前页的结束位置
    public Integer getEnd() {
        return end;
    }

    @Override
    public String toString() {
        return "$className{" +
                "pageNo=" + pageNo +
                ", pageSize=" + pageSize +
                ", total=" + total +
                ", totalPages=" + totalPages +
                ", result=" + result +
                ", start=" + start +
                ", end=" + end +
                '}';
    }
}
4.SunPageHelper.java
##定义初始变量
#set($className = "SunPageHelper")
##设置回调
$!callback.setFileName($className + ".java")
$!callback.setSavePath($tool.append($tableInfo.savePath, "/entity/page"))
##包名
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.entity.page;#end

import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Supplier;

/**
 * Description: 分页逻辑封装
 * @Author $!author
 * @Create $!time.currTime()
 * @Version 1.0
 */
public class $className {

    /**
     * 执行分页操作
     * @param pageNo 页码
     * @param pageSize 每页记录数
     * @param totalSupplier 获取总记录条数的逻辑
     * @param recordsSupplier 获取记录列表的逻辑
     * @param <T> 记录的类型
     * @return 分页结果
     */
    public static <T> PageResult<T> paginate(int pageNo, int pageSize,
                                             Supplier<Integer> totalSupplier,
                                             BiFunction<Integer, Integer, List<T>> recordsSupplier) {
        // 计算总记录数
        int total;
        try {
            total = totalSupplier.get();
        } catch (Exception e) {
            throw new RuntimeException("Failed to get total count", e);
        }
        
        // 如果总记录数为0,返回空的 PageResult
        if (total == 0) {
            return new PageResult.Builder<T>()
                    .pageNo(pageNo)
                    .pageSize(pageSize)
                    .total(total)
                    .result(Collections.emptyList()) // 空列表
                    .build();
        }

        // 计算 offset,表示从第几条记录开始查询
        int offset = calculateOffset(pageNo, pageSize);

        // 获取当前页的记录列表
        List<T> records;
        try {
            records = recordsSupplier.apply(offset, pageSize);
        } catch (Exception e) {
            throw new RuntimeException("Failed to get records", e);
        }

        // 使用 Builder 模式创建 PageResult 对象并返回
        return new PageResult.Builder<T>()
                .pageNo(pageNo)
                .pageSize(pageSize)
                .total(total)
                .result(records)
                .build();
    }

    /**
     * 计算分页的 offset
     * @param pageNo 页码
     * @param pageSize 每页记录数
     * @return offset
     */
    public static int calculateOffset(int pageNo, int pageSize) {
        // offset 计算公式:(当前页码 - 1) * 每页记录数
        return (pageNo - 1) * pageSize;
    }
}
5.Result.java
## 引入宏定义
$!{define.vm}

## 设置保存名称与保存位置
$!callback.setFileName("Result.java")
$!callback.setSavePath($tool.append($tableInfo.savePath, "/response"))

## 包声明
package $!{tableInfo.savePackageName}.response;

## 包导入
import lombok.Data;
import java.io.Serializable;

/**
 * Description: 通用响应封装类,通过枚举来获取code和message
 * @Author sun
 * @Create $!time.currTime("yyyy/MM/dd")
 * @Version 1.0
 */
@Data
public class Result<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    // 是否成功
    private boolean success;

    // 响应代码
    private int code;

    // 响应消息
    private String message;

    // 响应数据
    private T data;

    // 私有构造器,防止外部直接创建
    private Result() {}

    // 使用内部建造者类进行对象构建
    public static class Builder<T> {

        private boolean success;

        private int code;

        private String message;

        private T data;

        // ============================== 链式调用设置建造者对象 ==============================
        public Builder<T> success(boolean success) {
            this.success = success;
            return this;
        }

        public Builder<T> code(int code) {
            this.code = code;
            return this;
        }

        public Builder<T> message(String message) {
            this.message = message;
            return this;
        }

        public Builder<T> data(T data) {
            this.data = data;
            return this;
        }
        // ============================== 链式调用设置建造者对象 ==============================

        // ============================== 构建Result对象 ==============================
        public Result<T> build() {
            Result<T> result = new Result<>();
            result.success = this.success;
            result.code = this.code;
            result.message = this.message;
            result.data = this.data;
            return result;
        }
        // ============================== 构建Result对象 ==============================

    }

    // ============================== 快捷方法 ==============================
    public static <T> Result<T> ok() {
        return new Builder<T>()
                .success(true)
                .code(RespBeanEnum.SUCCESS.getCode())
                .message(RespBeanEnum.SUCCESS.getMessage())
                .build();
    }

    public static <T> Result<T> ok(T data) {
        return new Builder<T>()
                .success(true)
                .code(RespBeanEnum.SUCCESS.getCode())
                .message(RespBeanEnum.SUCCESS.getMessage())
                .data(data)
                .build();
    }

    public static <T> Result<T> ok(T data, String message) {
        return new Builder<T>()
                .success(true)
                .code(RespBeanEnum.SUCCESS.getCode())
                .message(message)
                .data(data)
                .build();
    }

    public static <T> Result<T> fail() {
        return new Builder<T>()
                .success(false)
                .code(RespBeanEnum.ERROR.getCode())
                .message(RespBeanEnum.ERROR.getMessage())
                .build();
    }

    public static <T> Result<T> fail(String message) {
        return new Builder<T>()
                .success(false)
                .code(RespBeanEnum.ERROR.getCode())
                .message(message)
                .build();
    }

    public static <T> Result<T> fail(int code, String message) {
        return new Builder<T>()
                .success(false)
                .code(code)
                .message(message)
                .build();
    }

    public static <T> Result<T> fail(RespBeanEnum respBeanEnum) {
        return new Builder<T>()
                .success(false)
                .code(respBeanEnum.getCode())
                .message(respBeanEnum.getMessage())
                .build();
    }
    // ============================== 快捷方法 ==============================

}
6.RespBeanEnum.java
## 引入宏定义
$!{define.vm}

## 设置保存名称与保存位置
$!callback.setFileName("RespBeanEnum.java")
$!callback.setSavePath($tool.append($tableInfo.savePath, "/response"))

## 包声明
package $!{tableInfo.savePackageName}.response;

## 包导入
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Description: 响应枚举类
 *
 * @Author $!{author}
 * @Create $!time.currTime("yyyy/MM/dd HH:mm")
 * @Version 1.0
 */

@Getter
@AllArgsConstructor
@ToString
public enum RespBeanEnum {
    // ============================== 枚举常量 ==============================
    // 通用
    SUCCESS(200, "成功"),
    ERROR(500, "失败"),
    // 可以在此处添加更多枚举常量,例如:
    // NOT_FOUND(404, "资源未找到"),
    // UNAUTHORIZED(401, "未授权"),
    ;
    // ============================== 枚举常量 ==============================

    // 响应码和响应信息
    private final Integer code;
    private final String message;

    /**
     * 将枚举转换为map(静态初始化)
     */
    public static final Map<Integer, RespBeanEnum> channelEnumMap = Stream.of(RespBeanEnum.values())
            .collect(Collectors.toMap(RespBeanEnum::getCode, Function.identity()));

    /**
     * 根据code来获取枚举
     */
    public static RespBeanEnum getByCode(int code) {
        return channelEnumMap.get(code);
    }

}

2.生成效果

CleanShot 2024-10-11 at 18.43.57@2x

3.导出到本地

CleanShot 2024-10-11 at 18.50.47@2x


网站公告

今日签到

点亮在社区的每一天
去签到