java MySQL如何获取唯一订单编号?
1. 前言
前提:系统并发量不大,数据库没有分库分表。
在实际开发工作中,有时需要我们设计唯一的订单编号。例如,编号格式为:ZHIFOU20240225000001
。我们的目标是在确保每天生成的订单编号唯一的前提下,最好使其自增长。
设计思路:
- 使用 SQL 查询当天创建时间的最大订单编号。
- 判断该编号是否存在:如果不存在,从
ZHIFOUYYYYMMDD000001
开始生成;如果存在,则对编号的数字部分自增。
2. 完整实现
2.1 mapper.xml
<mapper namespace="com.zhifou.OrderMapper">
<select id="getMaxOrderNumber" resultType="java.lang.String">
select max(order_number) as orderNumber
from zc_order
where DATE(create_time) = CURDATE()
</select>
</mapper>
该 SQL 语句用于查询当前日期的最大订单编号。
2.2 mapper
接口
public interface OrderMapper extends BaseMapper<Order> {
/**
* 获取今日最大订单编号
* @return 今日的最大订单编号
*/
String getMaxOrderNumber();
}
该接口提供获取今日最大订单编号的方法。
2.3 编号工具类(核心实现)
public class UniqueNumberUtil {
/**
* 获取唯一编号
* @param prefix 前缀
* @param todayMaxNumber 数据库中今天日期的最大编号
* @param numberLength 数字部分的位数
* @return 唯一编号
*/
public static String getUniqueNumber(String prefix, String todayMaxNumber, Integer numberLength) {
// 日期部分 (yyyyMMdd)
String dateParam = DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN);
// 数字部分
String number;
// 如果存在今日最大订单编号
if (StrUtil.isNotBlank(todayMaxNumber)) {
// 获取数字部分,例如 ZHIFOU20240201000001,数字部分是 "000001"
int num = Integer.parseInt(todayMaxNumber.substring(prefix.length() + 8));
num++; // 数字自增
// 如果自增后的数字长度不足,补0
if (String.valueOf(num).length() < numberLength) {
number = String.format("%0" + numberLength + "d", num);
} else {
number = String.valueOf(num);
}
} else {
// 如果不存在,初始编号为 000001
number = String.format("%0" + numberLength + "d", 1);
}
// 完整编号格式:前缀 + yyyyMMdd + 数字部分
return prefix + dateParam + number;
}
}
2.4 订单实体类
@Getter
@Setter
@Accessors(chain = true)
@TableName("wxg_order")
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String companyName;
private Long userId;
private String orderNumber;
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
}
2.5 测试用例
测试一:获取今日前缀为 ZHIFOU
的订单编号
@Autowired
private OrderMapper orderMapper;
@Test
void customTest() {
String orderNumber = UniqueNumberUtil.getUniqueNumber("ZHIFOU", this.orderMapper.getMaxOrderNumber(), 6);
System.out.println(orderNumber);
}
测试二:获取今日前缀为 ALIBABA
的订单编号
@Autowired
private OrderMapper orderMapper;
@Test
void customTest() {
String orderNumber = UniqueNumberUtil.getUniqueNumber("ALIBABA", this.orderMapper.getMaxOrderNumber(), 6);
System.out.println(orderNumber);
}
3. 总结
通过上述实现,我们可以确保每一天的订单编号都是唯一且自增长的。核心思想是基于数据库查询当天的最大编号,并通过数字部分自增来实现编号的连续性和唯一性。这种方案适用于系统并发量不大且没有分库分表的场景。