流水号在各种系统中随处可见,一般都是使用自增、年月日时分秒+自增、UUID等,要么纯数字,要么纯字母,这种流水号缺乏一定的辨识度。
下面为大家介绍一种具有辨识度的流水号的生成方式:领域或者应用的标识 + 表名的英文缩写(单词的第一个字母) + 年月日(或者年月日时分秒) + Oracle Sequence自增。
代码示例:
package com.pab.bloan.order.service;
* Created by
public interface SequenceGeneratorService {
* 根据SequenceName获取流水号
* @param prefix
* @param seqName
* @return
String getSerialNo(String prefix, String seqName);
* 根据指定的流水号的前缀、长度、SequenceName获取流水号
* @param prefix
* @param idLength
* @param seqName
* @return
String getSerialNo(String prefix, Integer idLength, String seqName);
package com.pab.bloan.order.service.impl;
import java.util.Date;
import lombok.extern.slf4j.Slf4j;
import com.pab.bloan.order.utils.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import com.pab.bloan.order.dao.bloanb.SequencePojoMapper;
import com.pab.bloan.order.service.SequenceGeneratorService;
import org.springframework.beans.factory.annotation.Autowired;
* 获取流水号服务
* Created by
@Slf4j
@Service
public class SequenceGeneratorServiceImpl implements SequenceGeneratorService {
@Autowired
private SequencePojoMapper sequencePojoMapper;
* {@inheritDoc}
* @param seqName
* @return
@Override
public String getSerialNo(String prefix, String seqName) {
return getSerialNo(prefix, 0, seqName);
* {@inheritDoc}
* @param prefix
* @param idLength
* @param seqName
* @return
@Override
public String getSerialNo(String prefix, Integer idLength, String seqName) {
try {
if (StringUtils.isEmpty(seqName)) {
return "";
if (idLength < 8){
idLength = 8;
} else if (idLength > 12){
idLength = 12;
String dateString = DateUtils.formatDate(new Date(),"yyyy/MM/dd");
dateString = dateString.replace("/", "");
StringBuilder sequenceSqlBuilder = new StringBuilder();
sequenceSqlBuilder.append(" select ");
sequenceSqlBuilder.append(seqName + ".NEXTVAL");
sequenceSqlBuilder.append(" FROM DUAL ");
Long sequenceId = sequencePojoMapper.getSequenceBySequenceName(sequenceSqlBuilder.toString());
String seqIdString = String.format("%0" + idLength + "d", sequenceId);
String serialNo;
if (seqIdString.length() > idLength) {
serialNo = String.format("%s%s%s", prefix, dateString, seqIdString.substring(seqIdString.length() - idLength, seqIdString.length()));
} else {
serialNo = String.format("%s%s%s", prefix, dateString, seqIdString);
return serialNo;
} catch (Exception e) {
log.error("SequenceGeneratorService.getSerialNo", e);
return "";
Mybatis Mapper.xml文件(不能使用缓存,因为在打开缓存的情况下,连续获取Sequence,会得到重复的值)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pab.bloan.order.dao.bloanb.SequencePojoMapper">
<select id="getSequenceBySequenceName" resultType="java.lang.Long"
useCache="false" flushCache="true">
${sql}
</select>
</mapper>
让自己业务中流水号具有辨识度,在关联查询时,一眼便可以看出数据源自何处。