我想给一个实体(发票,订单,预订等)一个唯一的序列号,但只在该年内唯一。因此,每年(或另一个字段,如客户)的第一张发票开始有id 1。这意味着可以有一个复合主键(年,id)或一个主键(即invoice_id)和另外两个列独一无二。使用复合主键生成自动增量ID
我的问题:使用Doctrine2和Symfony2为对象提供自动生成的ID和另一个值的唯一组合的最佳方式是什么?
复合键学说限制
学说不能分配一个自动生成的ID的实体与一个复合主键(http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html):
具有复合关键字的每个实体不能使用比“已分配”的其他 ID生成器。这意味着在您致电
EntityManager#persist($entity)
之前,ID字段必须设置其值 。
设置序列号手动
所以我必须手动分配一个ID。为了做到这一点,我试图在某一年寻找最高的ID,并给予ID + 1的新实体。我怀疑这是最好的方式,即使它是,我还没有找到最好的干)的方式来做到这一点。由于我认为这是一个通用的问题,我想阻止XY-problem,我已经开始了这个问题。
常规期权:只有MyISAM数据
我发现基于this answer的 '香草' 的MySQL/MyISAM的解决方案:
CREATE TABLE IF NOT EXISTS `invoice` (
`year` int(1) NOT NULL,
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`year`,`id`)
) ENGINE=MyISAM;
因为Doctrine2限制是行不通的,所以我我正在寻找这种香草MySQL解决方案的Doctrine ORM等价物。
其他解决方案
没有为InnoDB的一个解决方案,以及:Defining Composite Key with Auto Increment in MySQL
##畏缩的(可能)问题的常规期权是,你必须锁定**整个表**在您的交易期间,这相当于杀死了并发的INSERT。你为什么要每年重复IDS?一个实际的id值是没有意义的;如果要输出序列,请执行自连接和“COUNT()”。 –
由于财务原因,发票必须有序列号(每年以id = 1开头)。它不一定是主键的一部分,我会编辑我的问题。 –
不,好吧,是的,你可能确实需要骑自行车,然后持续的顺序......你可能无法摆脱这种做法,但至少可以解决表锁问题。将计数器存储在另一个表中(按年份键入),然后使用存储过程或触发器(在他们自己的事务中)将其打开。如果有人不提交他们的行,最终会出现差距,但至少长时间运行的交易不会锁定其他人。那么你只需要在这些列上使用'UNIQUE KEY'。 –