mysql 自增长通用单号生成

平时工作中我们经常会生成各种单号,大部分的单号都是日期加上自增长的序列如:VC20181115001,VC201811151525001,常用格式: 字母 + yyyyMMdd + 001,字母 + yyyyMMddHHmmss + 001等等。

我们可以使用mysql解决这个问题,使用存储过程调用,适合普通单号生成,不适合高并发的单号生成。

1.我们新建一张序列表 sys_sequence

 

CREATE TABLE `sys_sequence` (
  `name` varchar(32) NOT NULL,
  `value` int(10) DEFAULT NULL,
  `step` smallint(5) DEFAULT NULL,
  `start` int(10) DEFAULT NULL,
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 name 字段为我们设置的字母标识,value 字段为当前的序列号,step为每次增长的数字大小,start为起始数字

2.我们新建一个存储过程来调用生成序列,也可以用代码

 

CREATE PROCEDURE `generateSeq`(
IN m VARCHAR(100),OUT n INTEGER
)
BEGIN
   DECLARE t_error INTEGER DEFAULT 0;    
   DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error=1;    
   START TRANSACTION;  
     
   SET @v:= (SELECT EXISTS (SELECT `value` FROM `sys_sequence` WHERE `name`=m));  
   SET @m=0;  
   IF(@v=0) THEN
	INSERT INTO `sys_sequence`(`name`,`value`,`step`,`start`) VALUE(m,(SELECT @m:=1),1,1);
   ELSE
	 UPDATE `sys_sequence` SET `value`=@m:=`value`+1 WHERE `name`=m;  
   END IF;
   SET n=@m;  
   IF t_error =1 THEN    
       ROLLBACK;    
       SET n = -1;  
   ELSE    
        COMMIT;    
   END IF;  
    
   SELECT  n ;  
END

存储过程一个入参 name,一个出参n

首先根据传入的参数name查询出当前的序列值value,做个判断如果这个value值等于0则表示是第一次生成序列号,则默认即将生成的序列号为1,自增长为1,如果value值不等0则表示不是第一次生成序列号,则更新当前获取的序列号value值加1,最后在返回生成的序列号。

3.代码调用

我们可以用mybatis代码生成器生成表 sys_sequence 的代码,然后放进项目里,这里步骤省略。

SequenceService代码:

@Service
public class SequenceService {
    @Autowired
    private  SequenceExMapper sequenceExMapper

    //使用存储过程事物控制
    @Transactional(readOnly = false, propagation = Propagation.NOT_SUPPORTED)
    public int getSeq(String name){
        Sequence sq = new Sequence();
        sq.setName(name);
        int value = sequenceExMapper.getSeq(sq);
        return  value;
    }

}

SequenceExMapper代码:

@Repository
public interface SequenceExMapper {

    int getSeq(Sequence sequence);

}

SequenceExMapper.xml 代码:

<select  id="getSeq"  statementType="CALLABLE" resultType="INTEGER">
       {    CALL generateSeq(
           #{name,jdbcType=VARCHAR,mode=IN},
           #{value,jdbcType=INTEGER,mode=OUT})
       }
</select >

Sequence 对象代码:

public class Sequence implements Serializable{
    private static final long serialVersionUID = 1L;
    private java.lang.String name;//
    private java.lang.Integer value;//
    private Short step;//
    private java.lang.Integer start;//
	
    // 省略get和set方法
}

我们在需要生成单号的地方调用 SequenceService的getSeq方法即可,注意这个方法返回的只是一个当前的序列号数字如5,如果想要005这样的就需要我们再次拼接一下。

新建一个 CertificationService 代码:

@Service
public class CertificationService {
    private static Logger logger = LoggerFactory.getLogger(CertificationService.class);
    @Autowired
    private  SequenceService sequenceService;

    /**
     * 获取编码,格式如 VC20181115001
     * @return
     */
    public String getSeqDateNo() {
        int seqNo = sequenceService.getSeq("VC");
        String suffixCode =  String.format("%03d", seqNo);
        String currentDate = DateUtil.getDateStringCompact(new Date());
        String certificationNo = "VC" + currentDate + suffixCode;
        return certificationNo;
    }

    /**
     * 获取编码,格式如 VC201811151525001
     * @return
     */
    public String getSeqDateTimeNo() {
        int seqNo = sequenceService.getSeq("VC");
        String suffixCode =  String.format("%03d", seqNo);
        String currentDate = DateUtil.getDateTimeString4(new Date());
        String certificationNo = "VC" + currentDate + suffixCode;
        return certificationNo;
    }
} 

DateUtil的代码点击查看

猜你喜欢

转载自blog.csdn.net/zxl646801924/article/details/84105044