前几天做的一个需求,要求表中的主键按照yyyymmddhhmmss+3位从0开始当日递增。
接到这个需求的第一反应就是肯定要先获取当前时间,然后获取表中的最后一个ID。再截取今天的日期和表中最后一个ID的日期比较是否相等。如果相等,则获取最后三位并进行递增。反之,则从001开始。
具体代码如下:

import cn.hutool.core.date.DateUtil; // 导入日期工具类
import cn.hutool.core.util.RandomUtil; // 导入随机数工具类
import org.springframework.jdbc.core.JdbcTemplate; // 导入Spring JDBC模板类
import org.springframework.jdbc.datasource.DriverManagerDataSource; // 导入Spring JDBC驱动管理数据源类

import javax.annotation.Resource; // 导入javax标准注解,用于注入资源
import javax.sql.DataSource; // 导入数据源接口
import java.util.Date; // 导入日期类
import java.util.List; // 导入列表类

/**
 * NumUtil类用于生成唯一的ID编号。
 */
public class NumUtil {

    @Resource
    private JdbcTemplate jdbcTemplate; // Spring JDBC模板类

    private static final String DATE_FORMAT = "yyyyMMddHHmmss"; // 日期格式字符串:年月日时分秒

    /**
     * 创建并配置数据源对象
     * @return 数据源对象
     */
    private DataSource createDataSource() {
        DataSource dataSource = new DriverManagerDataSource(); // 创建Spring JDBC驱动管理数据源对象
        ((DriverManagerDataSource) dataSource).setDriverClassName("com.mysql.cj.jdbc.Driver"); // 设置数据库驱动类名
        ((DriverManagerDataSource) dataSource).setUrl(""); // 设置数据库连接URL
        ((DriverManagerDataSource) dataSource).setUsername(""); // 设置数据库用户名
        ((DriverManagerDataSource) dataSource).setPassword(""); // 设置数据库密码
        return dataSource;
    }

    /**
     * NumUtil类的构造方法,用于初始化JdbcTemplate对象
     */
    public NumUtil() {
        DataSource dataSource = createDataSource(); // 创建数据源对象
        jdbcTemplate = new JdbcTemplate(dataSource); // 初始化JdbcTemplate对象
        System.out.println("jdbcTemplate initialized."); // 打印初始化完成的信息
    }

    /**
     * 根据表名和列名生成一个新的ID编号
     * @param tableName 表名
     * @param columnName 列名
     * @return 生成的ID编号
     */
    public String createId(String tableName, String columnName) {
        String currentTime = getCurrentTime(); // 获取当前时间的字符串表示
        String lastId = getLastId(tableName, columnName); // 获取指定表中最后一个ID编号
        String increment = getIncrement(lastId, currentTime); // 获取自增的三位数字
        return currentTime + increment; // 返回生成的ID编号
    }

    /**
     * 获取当前时间的字符串表示,格式为"yyyyMMddHHmmss"
     * @return 当前时间的字符串表示
     */
    private String getCurrentTime() {
        return DateUtil.format(new Date(), DATE_FORMAT); // 使用日期工具类将当前时间格式化为指定的字符串格式
    }

    /**
     * 获取指定表中最后一个ID编号
     * @param tableName 表名
     * @param columnName 列名
     * @return 最后一个ID编号
     */
    private String getLastId(String tableName, String columnName) {
        // 确保在使用jdbcTemplate之前,它已经被正确初始化。
        if (jdbcTemplate == null) {
            throw new RuntimeException("JdbcTemplate has not been initialized."); // 如果jdbcTemplate为null,则抛出运行时异常
        }
        String sql = "SELECT " + columnName + " FROM " + tableName + " ORDER BY " + columnName + " DESC LIMIT 1"; // 构造查询最后一个ID编号的SQL语句
        List<String> result = jdbcTemplate.query(sql, (rs, rowNum) -> rs.getString(columnName)); // 使用jdbcTemplate查询数据库并返回结果列表
        if (result.isEmpty()) {
            return null; // 如果结果列表为空,则返回null
        }
        return result.get(0); // 否则返回结果列表中的第一个元素
    }

    /**
     * 获取自增的三位数字
     * @param lastId 最后一个ID编号
     * @param currentTime 当前时间的字符串表示
     * @return 自增的三位数字
     */
    private String getIncrement(String lastId, String currentTime) {
        if (lastId != null) {
            String lastDate = lastId.substring(0, 8); // 从最后一个ID编号中截取日期部分
            String currentDate = currentTime.substring(0, 8); // 从当前时间的字符串表示中截取日期部分
            if (lastDate.equals(currentDate)) {
                String increment = lastId.substring(14, 17); // 截取最后三位数字
                int incrementNumber = Integer.parseInt(increment); // 将截取到的字符串转换为整数
                incrementNumber++; // 自增1
                String newIncrement = String.format("%03d", incrementNumber); // 将新的数字转换为三位数的字符串形式,不足三位的数字前面补0.
                return newIncrement; // 返回自增的三位数字
            }
        }
        return "001"; // 如果当日不存在已有的ID编号,则从001开始自增。
    }
}

PS:上面代码中的注释都是用GPT生成的,目前GPT3.5真的很好用。我已经自用半年多了,正考虑自己做一个平台出来,进行商业化。

最后修改:2023 年 11 月 02 日
给我一点小钱钱也很高兴啦!o(* ̄▽ ̄*)ブ