代码之家  ›  专栏  ›  技术社区  ›  Michal Ciechan

复杂主键中Max(ID)的替代项

  •  1
  • Michal Ciechan  · 技术社区  · 15 年前

    我正在制作一个发票系统,支持多个子公司,每个子公司都有自己的发票号码集,因此我有一个主键为(Subsidiary,InvoiceNo)的表

    我不能使用MySQL auto increment字段,因为它将不断地为所有子项增加相同的计数。

    我不想为每个子公司做单独的表格,因为需要时会有新的子公司添加。。。

    我正在使用表中的“Select Max(ID)Where Subsidiary=X”,并根据此添加发票。

    我使用的是nHibernate,并且发票插入在InvoiceItem插入之前,因此如果发票插入失败,将不会执行InvoiceItem。但我将捕获异常,重新检索Max(ID)并重试。

    这种方法有什么问题?如果有的话,还有什么选择?

    我问这个问题的原因是因为我读了一个关于这个问题的答案: Nhibernate Criteria: 'select max(id)'

    2 回复  |  直到 9 年前
        1
  •  1
  •   Adrian Smith    15 年前

    正如您所说,这种方法的问题是多个会话可能会尝试插入同一发票ID。如果遇到唯一的约束冲突,则必须重试,这也可能会失败,依此类推。

    lock table 默认情况下,命令将 commit the transaction . (b) 两个不同子公司的发票没有理由不能同时添加,因为它们有不同的独立发票号。

    • 打开一个事务并确保您的表是InnoDB。
    • 用一个 SELECT .. FOR UPDATE LockMode.UPGRADE 在尼伯纳特。
    • 提交事务

        2
  •  3
  •   Pieter van Ginkel    15 年前

    在生成主键时使用这是一个非常糟糕的主意。我的建议如下:

    • 不要赋予主键业务含义(合成键);

    这会让你的生活更轻松。生成发票号码的机制可以是这样的表:

    • 附属的;
    • 下一个语音号码。

    这将把内部编号与数据库的工作方式分开。

    阅读材料的一些链接:

    http://fabiomaulo.blogspot.com/2008/12/identity-never-ending-story.html