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

时间:2015-03-30 21:07:39

标签: php mysql symfony doctrine-orm doctrine

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

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

据我所知,doctrine不支持自动生成复合主键的id,因此可以通过Doctrine保存数据并在复合键的一部分上自动增加。

请注意,在提交此问题之前,我已经研究了其他几个问题,例如:Defining Composite Key with Auto Increment in MySQLDoctrine: authorize NULL in a foreign composite key,我也多次阅读过Doctrine的文档,看看我是否遗漏了一些问题{ {3}}

主要问题是关于Doctrine

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值的行。

如何使用Doctrine执行相同的操作?有没有人知道完成工作的方法或解决方法?

1 个答案:

答案 0 :(得分:1)

这个问题没有简单的解决办法,但这里有几个选择:

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

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

示例:

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

实体模型需要告知id是否已生成,并且在pre-persist上需要为该id分配一个值,该值将来自此表中的entity_id + 1

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

这将导致运行2个额外的查询,一个在pre-persist上,另一个在post-persist上,这将使用新值更新sequencer表。

有一些策略可以避免在sequencer表上进行并发,因此它总是具有正确的值,其中一个是通过锁定表o.0

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

许多ORM不支持此问题,如果您遇到同样的问题,可能需要考虑上述问题之一。

现在,如果您专门使用Doctrine,我强烈建议您在IRC频道上寻求帮助。他们非常乐于帮助我为这个问题提供一些替代方案。