我目前有一个表,其主键是由id +外键组成的复合值。 id是自动递增的,外键引用另一个表。
在我保存数据的那一刻,我只知道外键值,我希望id从数据库返回给我作为自动增量号。
据我所知,doctrine不支持自动生成复合主键的id,因此可以通过Doctrine保存数据并在复合键的一部分上自动增加。
请注意,在提交此问题之前,我已经研究了其他几个问题,例如:Defining Composite Key with Auto Increment in MySQL和Doctrine: 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执行相同的操作?有没有人知道完成工作的方法或解决方法?
答案 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频道上寻求帮助。他们非常乐于帮助我为这个问题提供一些替代方案。