需求:
在数据库中,某个字段需要根据规则生成唯一的字段。格式:TK+年+月+日+0000(从001开始递增),例如:TK202404200001。
所以我们自己手写一个代码来生成对应的code,并且自增。下面的代码先定义了几个固定的字段,例如前缀TK,以及redis里面的key(redis可替换成自己的可以即可),存在redis里面主要是为了快速获取最新的值,并且唯一性。然后根据获取的值+1处理,再把前缀拼接起来,就组成了一个唯一的id。
而且还要根据redis里面的值判断是不是今天的,如果不是今天的,就从0001开始递增。
/**根据redis中有无缓存生成平台客户编码*/
private String createTkCustomerCode(){
String prefix = "TK";
String CUSTOMER_CODE_KEY = "CUSTOMER_CODE_KEY";
StringBuilder response = new StringBuilder();
String today = DateUtils.getReqDateyyyyMMdd(new Date());
String currentCustomerCode = redisHelper.strGet(CUSTOMER_CODE_KEY);
if (!StringUtils.isEmpty(currentCustomerCode) && isToday(prefix, currentCustomerCode)){
String number = currentCustomerCode.substring(currentCustomerCode.length() - 4);
int value;
try {
value = Integer.parseInt(number);
} catch (Exception e) {
Random random = new Random();
value = random.nextInt(4999) + 4999;
}
int increaseValue = value + 1;
String formatted = String.format("%04d", increaseValue);
response.append(prefix).append(today).append(formatted);
redisHelper.strSet(CUSTOMER_CODE_KEY, response.toString(),24, TimeUnit.HOURS);
return response.toString();
}
//redis中无值
response.append(prefix).append(today).append("0001");
redisHelper.strSet(CUSTOMER_CODE_KEY, response.toString(),24, TimeUnit.HOURS);
return response.toString();
}
/**判断是否是今天。eg:TK202404090001*/
private boolean isToday(String prefix, String data){
if (data.length() >= 14){
String keyToday = data.substring(0,data.length() - 4).toUpperCase();
String today = DateUtils.getCurrentDay("yyyyMMdd");
return Objects.equals(keyToday, prefix + today);
}
return false;
}
这个完全可以做成一个工具类来实现,就是要固定的格式,所以进阶版本如下代码。
进阶版本:
/***
* 根据自定义的prefix前缀,生成带时间戳的编码,输入编码前缀
* 前缀+年月日+4位流水号
*
* @param redisKey redis的key
* @param prefix 前缀
* @return
*/
public String getYYYYMMDD4Code(String redisKey, String prefix) {
Long sequenceId = 1L;
String reqDate = getReqDate();
String redisName = redisKey + reqDate + prefix;
if (redisHelper.strGet(redisName, Long.class) == null) {
redisHelper.strSet(redisName, String.valueOf(sequenceId), getNowToNextDayMilliSeconds(), TimeUnit.SECONDS);//redisHelper替换成自己的redis即可
} else {
sequenceId = redisHelper.strIncrement(redisName, 1L);
}
DecimalFormat format = new DecimalFormat("0000");
return prefix + reqDate + format.format(sequenceId);流水号
}
private final String YYYY_MM_DD_HH_MM_CODE_KEY = "business:app:YYYY_MM_DD_HH_MM_CODE_KEY:";
/**
* 生成带时间戳的编码,输入编码前缀
* 前缀+年月日时分+6位流水号
*/
public String getYYYYMMddHHmm6Code(String prefix) {
Long sequenceId = 1L;
String reqDate = new SimpleDateFormat("yyyyMMddHHmm").format(new Date());
String redisName = YYYY_MM_DD_HH_MM_CODE_KEY + reqDate + prefix;
if (redisHelper.strGet(redisName, Long.class) == null) {
redisHelper.strSet(redisName, String.valueOf(sequenceId), getNowToNextDayMilliSeconds(), TimeUnit.SECONDS);
} else {
sequenceId = redisHelper.strIncrement(redisName, 1L);
}
DecimalFormat format = new DecimalFormat("000000");
return prefix + reqDate + format.format(sequenceId);
}
public String getReqDate() {//yyyy-MM-dd 当前日期
return new SimpleDateFormat("yyyyMMdd").format(new Date());
}
但是这里还有一个问题,批量操作现有的数据,如果在单个线程里面操作,数据有5912条都需要530s,太耗时了,需要开线程来处理,这部分后面再聊。