【发布时间】:2014-06-17 17:33:39
【问题描述】:
我想给一个实体(发票、订单、预订等)一个唯一的序列号,但仅在该年内唯一。因此,每年的第一张发票(或其他字段,例如客户)开始时的 id 为 1。这意味着可以有一个复合主键(年份,id)或一个主键(即 invoice_id)和另外两个列一起独一无二。
我的问题:使用 Doctrine2 和 Symfony2 为对象提供自动生成的 ID 和另一个值的唯一组合的最佳方法是什么?
复合键的原则限制
Doctrine 无法将自动生成的 ID 分配给具有复合主键 (http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html) 的实体:
每个具有复合键的实体都不能使用其他的 id 生成器 比“分配”。这意味着 ID 字段必须有它们的值 在致电
EntityManager#persist($entity)之前设置。
手动设置序号
所以我必须手动分配一个 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 的限制,这不起作用,所以我正在寻找与这个 vanilla MySQL 解决方案等效的 Doctrine ORM。
其他解决方案
InnoDB 也有一个解决方案:Defining Composite Key with Auto Increment in MySQL
【问题讨论】:
-
#winces# vanilla 选项的(可能)问题是您必须在事务期间锁定整个表,这会杀死并发
INSERTs。为什么要每年重复 id?一个实际的 id 值是没有意义的;如果你想输出一个序列,做一个自连接和COUNT()。 -
出于财务原因,发票必须有一个序列号(每年从 id=1 开始)。它不必是主键的一部分,我将编辑我的问题。
-
不,好吧,是的,你可能确实需要一个循环的、持续的序列......你可能无法摆脱制作这个每年连续播放,但你至少可以解决表锁定问题;将计数器存储在另一个表中(按年份键),然后使用存储过程或触发器(在他们自己的事务中)对其进行命中。如果有人不提交他们的行,那么您最终会出现差距,但至少长期运行的事务不会将其他所有人拒之门外。那么你只需要在这些列上添加一个
UNIQUE KEY。 -
这听起来是个好主意,但我不确定我是否真的理解它。我如何在 Symfony2/Doctrine ORM 中实现它?
-
@Clockwork-Muse 我知道您是 SQL 专家。我想到了我找到的 vanilla 解决方案的 Symfony2/Doctrine 实现。您同意还是正在考虑替代计划?
标签: php mysql sql symfony doctrine-orm