具有要自动生成的复合主键的一个字段的条令



我目前有一个表,它有一个由id+外键组成的复合值作为主键。id自动递增,外键引用另一个表。

在我保存数据的那一刻,我只知道外键值,我希望id作为一个自动递增的数字从数据库返回给我。

我知道doctrine不支持自动生成复合主键的id,所以可以做些什么来允许doctrine保存数据,并且在复合密钥的一部分上仍然具有自动增量。

注意,在提交这个问题之前,我已经研究了其他几个问题,例如:在MySQL和Doctrine中定义具有自动增量的复合密钥:在外部复合密钥中授权NULL,我还多次阅读了Doctrine的文档,看看我是否遗漏了什么http://doctrine-orm.readthedocs.org/en/latest/tutorials/composite-primary-keys.html#use-案例1-动力学属性

主要问题是关于原则

Every entity with a composite key cannot use an id generator other than
“ASSIGNED”. That means the ID fields have to have their values set before
you call EntityManager#persist($entity).

为了帮助解决这个问题,这里有一个如何构建表的例子:

create table composite_example (
    id int(11) not null auto_increment,
    fk_id int(11) not null,
    a_prop varchar(20),
    primary key (id, fk_id)
) engine=InnoDB default charset=utf8;

如果我必须手动构建一个MySQL查询来插入到这个表中,并且知道fk_id和a_prop的值,我可以做:

insert into composite_example (fk_id, a_prop) values (999, 'a_value');

它将在表上创建一个具有适当id值的行。

我怎么能用条令做同样的行为?有人知道完成这项工作的方法或变通方法吗?

这件事没有简单的解决方案,但这里有几个选项:

1) 您可以删除复合密钥并使用UUID作为密钥。这不是一个简单的解决方案,因为它会影响需要更改的代码数量、迁移所需的时间以及对性能的影响。

2) 另一种选择是Doctrine社区提出的,也可以在其他ORM中使用:使用测序仪。对于此解决方案,您需要创建一个表,在其中存储实体标识符,下一列将是该标识符的最后一个值。

示例:

Table sequencer
id | entity_name | entity_id
88 | customers   | 77

实体模型需要通知id已经生成,并且在预持久化时,它需要为该id分配一个值,该值将来自该表中的entity_id+1

select max(entity_id)+1 from sequencer where entity_name = 'customers';

这将导致额外运行2个查询,一个在预持久化上,另一个在后持久化上——这将用新值更新序列表。

有一些策略可以避免序列表上的并发,这样它就总是有正确的值,其中之一就是锁定表o.0

3) 您可以编写自己的加载器和持久器,但此时您可能会面临与UUID实现一样大的更改。

很多ORM都不支持这一点,如果你面临同样的问题,你可能不得不考虑上面的一个。

现在,如果你正在专门与Doctrine合作,我强烈建议你在IRC频道上寻求帮助。他们非常有帮助,为我提供了一些解决这个问题的替代方案。

相关内容

  • 没有找到相关文章

最新更新