MYSQL 自动递增主键的实际问题



>我最近为我的java应用程序编写了一个会计模块。

该模块基于MYSQL表和INNODB引擎。其中一个要求当然是每张发票的"运行"ID。我尝试使用 auto_increment 方法和序列表生成 id,但在两者中我都有相同的问题:由于 id 是在我保留发票实体时生成的,如果在将持久实体刷新到数据库期间发生错误,auto_id将递增,导致我的一系列发票出现"漏洞"。我当然可以放弃这种方法,并分配具有以前发票的最大ID+ 1的新发票,但我认为这是一种不好的做法。我可以使用哪些其他方法来确保我的发票系列中没有漏洞,假设发票偶尔会由于某些验证问题而无法保存。

在 spring 框架中,有类似的东西

@Transactional(rollbackFor=RuntimeException.class)

因此,如果服务器调用出现问题,则所有内容都应回滚。我相信其他框架也有类似的方法。

>如果您的MySQL版本>5.0.2,那么您可以尝试使用触发器来正确增加表列的值。但是您应该记住,将发票编号的生成委托给数据库,我认为这与业务逻辑更相关,这不是一个好主意,因为在失败的情况下,您可能会遇到一些问题。所以我宁愿建议你在代码中以编程方式生成它。

这本身并不是不好的做法,但可能值得使用不同的"传统"数字主键字段来保证表的结构完整性,并为发票编号使用另一个字段。

然后,您可以使用不同的逻辑填充该发票编号,或者只是一个简单的MAX+1,或者通过从键表中查找,以允许不同类型的发票使用不同的编号序列。

例如:

CREATE TABLE `keys` (
    `id` INT NOT NULL auto_increment,
    `type` VARCHAR(10) NOT NULL,
    `prefix` VARCHAR(10) NOT NULL,
    `value` INT(10) NOT NULL DEFAULT 0,
    PRIMARY KEY (`id`)
);
INSERT INTO `keys` (`type`, `prefix`) VALUES
('Sales Receipt', 'SRI'),
('Sales Invoice', 'SIN'),
('Sales Refund', 'SRF');

然后在您的(伪)代码中,您可以执行

Database.BeginTransaction;
NewInvNum = Database.Query("SELECT `value` FROM `keys` WHERE `type` = 'SIN'");
MyInvoice.InvoiceNumber = NewInvNum;
Database.SaveInvoice(MyInvoice);
Database.Query("UPDATE `keys` SET `value` = {0} WHERE `type` = 'SIN'", NewInvNum+1);
Database.CommitTransaction;

事务(或其他一些并发保护)很重要,因此当创建多个发票时,它们不会获得相同的编号。

最新更新