产生自定义格式的自动增长序列号
产生自定义格式的自动增长序列号:
- /**
- * 自己维护的序列号,至少从1开始增长
- */
- public abstract class IncrementNumber {
- public IncrementNumber() {}
- public IncrementNumber(int interval, int maxNum) {
- this.interval = interval;
- this.maxNum = maxNum;
- }
- public synchronized int cal() throws Exception {
- if (serialNum == -1) {
- serialNum = initStartNum(); // 已经使用的序列号一定 小于 缓存的序列号
- intervalMax = serialNum + interval;
- updateStartNum(intervalMax);
- return serialNum;
- }
- if (isMax(serialNum)) { // 达到预定的最大值
- resetSerialNum();
- return serialNum;
- }
- serialNum++;
- if (serialNum >= (intervalMax - 1)) { // 到达区间最大值
- intervalMax += interval;
- updateStartNum(intervalMax);
- }
- return serialNum;
- }
- /**
- * 初始化序列号,从缓存系统中来,比如数据库、文件等
- * @return 初始序列号
- * @throws Exception
- */
- public abstract int initStartNum() throws Exception;
- /**
- * 更新区间最大值到缓存系统,比如数据库、文件中。
- * @param intervalMax 区间最大值
- * @throws Exception
- */
- public abstract void updateStartNum(int intervalMax) throws Exception;
- /**
- * 重置序列号,从1开始
- */
- protected void resetSerialNum() throws Exception {
- this.serialNum = 1;
- intervalMax = serialNum + interval;
- updateStartNum(intervalMax);
- }
- /**
- * 是否是最大值
- * @param num
- * @return
- */
- private boolean isMax(int num) {
- return num >= maxNum;
- }
- public int getInterval() {
- return this.interval;
- }
- public int getMaxNum() {
- return this.maxNum;
- }
- /** 区间最大值 */
- protected int intervalMax = 0;
- /** 每次增加量 */
- protected int interval = 20;
- /** 预定的最大值 */
- protected int maxNum = 9999;
- /** 序列号 */
- protected int serialNum = -1;
- }
使用方法:
- @Service
- @Transactional
- public class TableKeyManager extends IncrementNumber {
- public TableKeyManager() {
- super(100, 99999999);
- }
- @Override
- public int initStartNum() throws Exception {
- TableKey tableKey = tableKeyDao.getById(name);
- date = DateConvertUtils.getDayEnd(DateConvertUtils.parse(tableKey.getDate(), "yyMMdd"));
- dateEndMillis = date.getTime();
- prefix = tableKey.getDate();
- return (int) tableKey.getMaxNum();
- }
- @Override
- public void updateStartNum(int intervalMax) throws Exception {
- TableKey tableKey = tableKeyDao.getById(name);
- tableKey.setDate(DateConvertUtils.format(new Date(dateEndMillis), "yyMMdd"));
- tableKey.setMaxNum(intervalMax);
- tableKeyDao.update(tableKey);
- }
- public String getNum() {
- try {
- long now = System.currentTimeMillis();
- int no = 0;
- if (now > dateEndMillis) {
- date = DateConvertUtils.getDayEnd(new Date(now));
- dateEndMillis = date.getTime();
- prefix = DateConvertUtils.format(date, "yyMMdd");
- resetSerialNum();
- no = this.serialNum;
- } else {
- no = cal();
- }
- return prefix + ApplicationUtil.getFixedSizeNum(no, 8);
- } catch (Exception e) {
- e.printStackTrace();
- }
- throw new RuntimeException("生成序列号错误");
- }
- public void setName(String name) {
- this.name = name;
- }
- private String prefix = null;
- private long dateEndMillis = 0l;
- private Date date = null;
- private String name;
- @Autowired
- private TableKeyDao tableKeyDao;
- }
这种方法仅在初始化时查询一次数据库,在每次到达增长上限时,计数自动叠加一个步长,同时更新数据库中的数据上限。
table_key的数据结构
- CREATE TABLE `table_key` (
- `key_name` varchar(100) NOT NULL COMMENT '需要维护的key名称',
- `cur_no` mediumtext COMMENT '当前数据编号',
- `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '数据编号更新时间',
- `create_time` datetime DEFAULT NULL COMMENT '记录创建时间',
- PRIMARY KEY (`key_name`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8