我最近为我的java应用程序编写了一个会计模块。
该模块基于MYSQL表和INNODB Engine。
其中一个要求当然是每张发票的“运行”ID。
我尝试使用auto_increment
方法和使用序列表生成id,但在两者中我都有同样的问题:因为当我持久保存发票实体时生成id,如果在刷新期间发生错误持久化实体到数据库,auto_id递增,在我的系列发票中造成“漏洞”。
我当然可以放弃这种方法,并为新发票分配以前发票的最大ID + 1,但我认为这是一种不好的做法。我可以使用哪些其他方法来确保我的发票系列中没有漏洞,假设由于某些验证问题导致发票偶尔无法保存。
答案 0 :(得分:1)
在spring框架中有类似
的东西@Transactional(rollbackFor=RuntimeException.class)
所以如果服务器调用出现问题,应该回滚一切。我确信其他框架也有类似的方法。
答案 1 :(得分:0)
如果你的MySQL版本> 5.0.2然后你可以尝试使用触发器,它会正确地增加表列的值。 但你应该记得,委托给数据库的发票编号的生成,这与业务逻辑更相关,我认为,这不是一个好主意,因为在失败的情况下你可能会遇到一些问题。所以我建议你在代码中以编程方式生成它。
答案 2 :(得分:0)
这本身并不差,但可能值得拥有一个不同的“传统”数字主键字段来保证表格的结构完整性,并为发票号码设置另一个字段。
然后,您可以使用不同的逻辑填充该发票编号,或者只是简单的 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;
事务(或其他一些并发保护)很重要,因此当正在创建多个发票时,它们不会得到相同的数字。