标签:实体类 sha ase 标识 pattern blog 了解 nal and
本次采用mysql处理,性能不是很好,对于高并发有要求的建议不要采用
公司一个小项目,需要生成一个单据号,格式为: 日期 + 每日重新自增号,自己考虑了一下每日自增需要考虑并发和持久问题,两种数据库redis和mysql由于项目较小,所以没有redis因为这个增加一个redis好像有点不值得,所以采用mysql作为持久化处理,一下思路也是借鉴了网上的许多想法
源码查看规则
源码位置: blog-study:module-utils:work-no
欢迎大家随时批评指正
/**
* 业务唯一标识(只是作为唯一标识,并不参与单据号的生成)
*/
private String workNo;
/**
* 业务码前缀
*/
private String prefix;
/**
* 序号
*/
private Integer serialNum;
/**
* 序号长度
*/
private Integer serialLength;
/**
* 序号之后的随机数长度(干扰串)
*/
private Integer randomLength;
/**
* 重置模式(0:无需重置,1: 按天重置, 2: 按月重置, 3: 按年重置)
*/
private Integer restType;
/**
* 重置时间(检测是否需要重置使用)
*/
private LocalDate restTime;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 修改时间
*/
private LocalDateTime updateTime;
/**
* 备注
*/
private String remark;
/**
* 为了保证每次生成的单号一致性,所以初始化作为第一次初始化成功后不再修改
*/
ORDER_NO("XG", "XG", 5, 2, 1, "小郭测试单据号");
/**
* 业务唯一标识(只是作为唯一标识,并不参与单据号的生成)
*/
private String workNo;
/**
* 业务码前缀
*/
private String prefix;
/**
* 序号长度
*/
private Integer serialLength;
/**
* 序号之后的随机数长度(干扰串)0代表没有干扰
*/
private Integer randomLength;
/**
* 重置模式(0:无需重置,1: 按天重置, 2: 按月重置, 3: 按年重置)
*/
private Integer restType;
/**
* 备注
*/
private String remark;
项目启动初始化:
@Configuration
public class WorkNoInit implements ApplicationRunner {
@Autowired
private WorkNoDao workNoDao;
/**
* 单据号初始化
*
* @param args
* @throws Exception
*/
@Override
public void run(ApplicationArguments args) throws Exception {
WorkNoInfo workNoInfo = null;
for (WorkInfoEnum workInfoEnum : WorkInfoEnum.values()) {
workNoInfo = new WorkNoInfo(workInfoEnum);
//查询是否已有该业务单据号(没有初始化)
if (workNoDao.isHaveWorkNo(workNoInfo.getWorkNo()) == 0) {
workNoDao.addOrderNumInfo(workNoInfo);
}
}
}
}
@Component
public class WorkNoService {
@Autowired
private WorkNoDao workNoDao;
private static Lock lock = new ReentrantLock();
/**
* 获取业务序列码
*
* 流程:
* 1. 加锁保证线程安全
* 2. 查询数据库中的业务信息
* 3. 判断重置模式修改数据库中相应的数据
* 4. 返回业务码
*
* @param workInfoEnum 枚举
* @return 业务序列码
*/
public String getOrderNo(WorkInfoEnum workInfoEnum) {
lock.lock();
LocalDateTime localDateTime = LocalDateTime.now();
try {
WorkNoInfo workNoInfo = workNoDao.queryByWorkNo(workInfoEnum.getWorkNo());
if (workNoInfo == null) {
throw new ErrorCodeException(500, "查询生成业务码基础数据失败!");
}
//序号
Integer serialNum = workNoInfo.getSerialNum();
//判断是否需要重置序号
if (workNoInfo.getRestType() == 1) {
String dayTime = localDateTime.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
String dataBaseTime = workNoInfo.getRestTime().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
if (!dataBaseTime.equals(dayTime)) {
serialNum = 0;
}
} else if (workNoInfo.getRestType() == 2) {
String monthTime = localDateTime.format(DateTimeFormatter.ofPattern("yyyyMM"));
String dataBaseTime = workNoInfo.getRestTime().format(DateTimeFormatter.ofPattern("yyyyMM"));
if (!dataBaseTime.equals(monthTime)) {
serialNum = 0;
}
} else if (workNoInfo.getRestType() == 3) {
String yearTime = localDateTime.format(DateTimeFormatter.ofPattern("yyyy"));
String dataBaseTime = workNoInfo.getRestTime().format(DateTimeFormatter.ofPattern("yyyy"));
if (!dataBaseTime.equals(yearTime)) {
serialNum = 0;
}
}
workNoInfo.setSerialNum(serialNum + 1);
workNoInfo.setRestTime(localDateTime.toLocalDate());
//更新数据库
workNoDao.updateOrderNo(workNoInfo);
return workNoInfo.getNo();
} catch (Exception e) {
throw new ErrorCodeException(500, "生成业务码失败" + e.getMessage());
} finally {
lock.unlock();
}
}
}
标签:实体类 sha ase 标识 pattern blog 了解 nal and
原文地址:https://www.cnblogs.com/chunyun/p/12128430.html