springboot中按日期生成当天唯一编码
现在有一个场景给每一个单据赋码,单据编码的规则是前缀 + 当天日期 + 00001开始排序,例如当天就是DG2024101500001,那么下次创建就是DG2024101500002,第二天就是DG2024101600001。
故现在创建一个简易工具类去获取编码,传入前缀和当天日期的获取规则即可。为了适配不同的业务逻辑和数据类型,我们可能需要使用一些泛型和函数接口。
NumberGeneratorUtil.java
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.function.Function;
public class NumberGeneratorUtil {
public static <T> String generateNumber(String prefix, Function<LocalDate, List<T>> finder, Function<T, String> numberExtractor) {
LocalDate today = LocalDate.now();
// 使用finder应用查询,获取当天创建的所有记录
List<T> entityList = finder.apply(today);
// 设置日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String currentDate = sdf.format(new Date());
String newNumber = prefix + currentDate + "00001";
if (entityList == null || entityList.isEmpty()) {
return newNumber;
}
while (true) {
boolean isUnique = true;
for (T entity : entityList) {
if (numberExtractor.apply(entity).equals(newNumber)) {
isUnique = false;
break;
}
}
if (isUnique) {
break;
}
int lastDigits = Integer.parseInt(newNumber.substring(newNumber.length() - 5));
lastDigits++;
newNumber = prefix + currentDate + String.format("%05d", lastDigits);
}
return newNumber;
}
}
使用泛型和函数式接口 在这个工具类中,我们使用了Java的泛型 <T> 和函数式接口 Function,这使得我们的 generateNumber 方法能够适用于多种数据类型和业务逻辑。
泛型 <T>:使得这个工具类可以处理任何类型的实体。
函数式接口 Function:Function<LocalDate, List<T>> finder 用于根据日期查找当天的记录。 Function<T, String> numberExtractor 用于从实体中抽取编号字符串。
使用
@Autowired
private WorkDispatchService workDispatchService;
public String createWorkDispatchNumber() {
return NumberGeneratorUtil.generateNumber("PG",
(date) -> { // 这里可以直接调用服务层的方法来查询当天的记录
LambdaQueryWrapper<WorkDispatch> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WorkDispatch::getIsDeleted, 0)
.ge(WorkDispatch::getCreateTime, date.atStartOfDay())
.le(WorkDispatch::getCreateTime, date.atTime(23, 59, 59));
return workDispatchService.list(queryWrapper);
},
WorkDispatch::getNumber // 从WorkDispatch实例中提取编号的方法引用
);
}
通过这种方式,我们创建了一个非常灵活的编号生成工具,它可以被用于不同的业务场景中,只需要传递对应的业务逻辑和数据处理逻辑。