java环境下,订单号或者流水号的生成方法(1)

news/2025/2/26 13:41:55

方法一:

(一).订单号、流水号要求:

  1. 单数据库下支持高并发
  2. 唯一的新单号,不保证连续性
  3. 不保存数据库内唯一,保证表内唯一

 (二).设计思路

  1. 如何保证数据唯一?

       先看下单号样例:A04190701000001 。

       A04:组织代码,190701:当前年月日,000001:可变长度流水号。

       通过组织代码+当前年月日+定长流水号,保证单表内唯一。

     2.如何保证单表为唯一?

       数据库中记录的形式。数据库中将存在流水生成记录表,记录如下字段:

       name(PO对象class名_组织代码_当前年月日),value(当前生成次数)。

       生成sql存储过程,获取流水序号。

(三).代码实现

/**
 * 生成序列号的工具。 <br>
 * 可支持单数据库的并发操作。
 */
public class SequenceGenerator {
  private static final SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
  private static final int DEFAULT_FLOW_NO_LEN = 6;

  /**
   * 生成定长序列号。
   * 
   * @param name
   *          名称
   * @param len
   *          长度
   * @return
   * @throws ServiceException
   */
  public static String nextValue(String name, int len) throws ServiceException {
    Assert.assertArgumentNotNull(name, "name");

    int value = nextValue(name);
    return String.format("%0" + len + "d", value);
  }

  /**
   * 生成序列号。
   * 
   * @param name
   *          序列名称。
   * @return
   * @throws ServiceException
   */
  public static int nextValue(String name) throws ServiceException {
    Assert.assertArgumentNotEmpty(name, "name");

    String sql = "select _nextval(?) v";
    ICommonDao commonDao = ApplicationContextUtil.getBean(ICommonDao.class);
    Map<String, Object> results = commonDao.findOneForJdbc(sql, name);
    if (results.size() <= 0) {
      throw new ServiceException("生成序列号失败");
    }

    Object value = results.get("v");
    if (value == null) {
      throw new ServiceException("生成序列号失败");
    }
    return (Integer) value;
  }

  /**
   * 生成单号。 <br>
   * 默认6位流水号
   * 
   * @param billClass
   *          单据对象类。
   * @return 唯一的新单号,但不保证连续性。
   * @throws ServiceException
   */
  public static String nextBillNumber(Class<?> billClass) throws ServiceException {
    return nextBillNumber(billClass.getSimpleName(), DEFAULT_FLOW_NO_LEN);
  }

  /**
   * 生成单号。 <br>
   * 默认6位流水号
   * 
   * @param billType
   *          单据类型,一般取实体短名称,禁止为null。
   * @return 唯一的新单号,但不保证连续性。
   * @throws ServiceException
   */
  public static String nextBillNumber(String billType) throws ServiceException {
    return nextBillNumber(billType, DEFAULT_FLOW_NO_LEN);
  }

  /**
   * 生成单号。
   * 
   * @param billType
   *          单据类型,一般取实体短名称,禁止为null。
   * @param flowNumLenth
   *          流水号长度。-1表示不固定长度。
   * @return 唯一的新单号,但不保证连续性。
   * @throws ServiceException
   */
  public static String nextBillNumber(String billType, int flowNumLenth) throws ServiceException {
    final String orgCode = "A04";
    return nextBillNumber(billType, orgCode, flowNumLenth);
  }

  /**
   * 生成单号。 <br>
   * 生成规格: 5位组织代码 + 6位日期(yyMMdd) + flowNumLenth位流水号。 其中,流水号每日重复计算。 <br>
   * 示例: 00001 161206 00001
   * 
   * @param billType
   *          单据类型,一般取实体短名称,禁止为null。
   * @param orgCode
   *          当前组织代码,可空。
   * @param flowNumLenth
   *          流水号长度。-1表示不固定长度。
   * @return 唯一的新单号,但不保证连续性。
   * @throws ServiceException
   */
  public static String nextBillNumber(String billType, String orgCode, int flowNumLenth)
      throws ServiceException {
    Assert.assertArgumentNotEmpty(billType, "billType");

    String suffix = StringUtils.trimToEmpty(orgCode);
    if (StringUtils.isNotBlank(suffix)) {
      suffix += "_";
    }
    final String dateStr = sdf.format(new Date());
    suffix += dateStr;

    // 取流水号
    final String key = billType + "_" + suffix;
    final int value = nextValue(key);
    String test = String.format("%s%" + (flowNumLenth < 0 ? "" : "0" + flowNumLenth) + "d",
        orgCode + dateStr, value);
    return test;
  }

  /**
   * 取当前组织代码
   * 
   * @return
   * @throws ServiceException
   */
  private static String getCurrentOrgCode() throws ServiceException {

  }

}
-- sql存储过程
begin  
  declare bExists int;
  
  select count(1) into bExists from wm_sequence where `_name` = in_name;
  if bExists = 0 then 
    INSERT INTO `wm_sequence`(`_name`, `_value`) VALUES (in_name, 0);
  end if;
  
  update wm_sequence SET _value = LAST_INSERT_ID(_value+1) where _name = in_name;
  return (select LAST_INSERT_ID());
end

 


http://www.niftyadmin.cn/n/1485117.html

相关文章

yum 命令全集

yum check-update 检查可更新的所有软件包 yum update 下载更新系统已安装的所有软件包 yum upgrade 大规模的版本升级,与yum update不同的是,连旧的淘汰的包也升级 yum install <packages> 安装新软件包 yum update <packages> 更新指定的软件包 yum remove …

用python快速做表_用Python快速处理表格,让你快人一步两步三四部

日常工作中表格处理时非常令人头疼的一个部分&#xff0c; 概念 CSV (Comma Separated Values)&#xff0c;即逗号分隔值&#xff08;也称字符分隔值&#xff0c;因为分隔符可以不是逗号&#xff09;&#xff0c;是一种常用的文本 格式&#xff0c;用以存储表格数据&#xff0c…

MySQL 学习笔记(三):完整性和触发器设计

&#xff08;一&#xff09;完整性设计 方法一、在设计表时定义约束 删除数据库school,建立新数据库school1 drop database school; create database school; use school; 1.定义约束 create table Student(Sno char(9) primary key, /*主键约束 提示primary key */ Sname …

树莓派 换源_树莓派Raspbian minimal image下载站搭建

树莓派Raspbian minimal image下载站搭建烧写镜像下载镜像Balena Etcher烧写镜像&#xff0c;准备一张空的SD卡&#xff0c;选择好镜像和SD卡&#xff0c;直接Flash等待烧写完毕。启动系统把卡插入&#xff0c;开机&#xff0c;通过HDMI显示输出&#xff0c;就有命令行界面了。…

System.Web.HttpException: 类型“TextBox”的控件“ctl02_TextBox2”必须放在具有 runat=server 的窗体标记内。...

目的&#xff1a;加入用户自定义控件 错误提示&#xff1a;System.Web.HttpException: 类型“TextBox”的控件“ctl02_TextBox2”必须放在具有 runatserver 的窗体标记内。 沒有ctl02_TextBox2这个控件啊&#xff1f; WebUserControl.ascx 代码 <% Control …

如何使用httpClient的形式调用WebService接口?

工作中接到一份新需求&#xff1a;调用第三方短信接口&#xff0c;实现验证码接收。 第三方提供&#xff1a; 1.wsdl形式的接口文档地址&#xff1a; 2.浏览器中访问该文档地址&#xff1a; 3.下载soapUi工具&#xff0c;测试该文档接口。&#xff08;我使用的是ReadyApi工具…

YAML基础教程

一、YAML介绍 YAML参考了其他多种语言&#xff0c;包括&#xff1a;XML、C语言、Python、Perl以及电子邮件格式RFC2822。Clark Evans在2001年5月在首次发表了这种语言&#xff0c;另外Ingy dt Net与Oren Ben-Kiki也是这语言的共同设计者。YAML是"YAML Aint a Markup Langu…

陈俊宏:HTML5 APP与云端应用整合

HTML5 综述 HTML5 将移动终端与云计算融为一体&#xff0c;所以它不只是技术&#xff0c;更是一种新概念&#xff0c;是一种各行各种都要把服务往移动终端整合的新概念。 概念上&#xff0c;HTML5 Mobile Cloud&#xff0c;商业模式将开始起大变化。因为 HTML5&#xff0c;您…