我们有一个数据库模式,以简化(略微设计)的形式,如下所示:
从用户到域的外键设置在列(domainId,groupId)上,以保证参照完整性.该结构适用于预期目的.
但是,对于与同一数据库通信的新应用程序,我现在需要为Doctrine创建映射上述结构的映射,包括两列上的外键关系.
我尝试过以下方法:
但这给了我一个错误:
UnitOfWork.PHP第2649行:未定义的索引:groupId
所以,我的问题是:
在Doctrine中描述多列多对一外键关系的正确方法是什么?
CREATE TABLE `users` (
`userId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,`groupId` INT(10) UNSIGNED NOT NULL,`domainId` INT(10) UNSIGNED NOT NULL,`someData` VARCHAR(32),PRIMARY KEY (`userId`),KEY `key_users_groupId_domainId` (`groupId`,`domainId`)
) ENGINE=InnoDB;
CREATE TABLE `domains` (
`domainId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,`someOtherData` VARCHAR(32),PRIMARY KEY (`domainId`),KEY `key_domains_groupId` (`groupId`)
) ENGINE=InnoDB;
CREATE TABLE `groups` (
`groupId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,`someMoreData` VARCHAR(32),PRIMARY KEY (`groupId`)
) ENGINE=InnoDB;
ALTER TABLE `users`
ADD CONSTRAINT `fk_users_domains` FOREIGN KEY (`groupId`,`domainId`) REFERENCES `domains` (`groupId`,`domainId`),ADD CONSTRAINT `fk_users_groups` FOREIGN KEY (`groupId`) REFERENCES `groups` (`groupId`);
ALTER TABLE `domains`
ADD CONSTRAINT `fk_domains_groups` FOREIGN KEY (`groupId`) REFERENCES `groups` (`groupId`);
Doctrine multiple composite foreign key,一个问题,虽然它没有显示XML映射,并且可能是偏离基础的,至少它似乎是关于FK中的多列.并根据答案回答关于Doctrine2的某些方面的问题.
Doctrine2 Map entities with composite foreign keys in …一个问题虽然没有多大价值,但至少可以作为一个骗子候选人加入你的问题.
XML Mapping Doctrine2 XML映射文档.搜索文本多重没有价值,但搜索复合材料时说:
For composite keys you can specify more than one id-element,however
surrogate keys are recommended for use with Doctrine 2.
这让我想到了代理商Wikipedia的定义:
The surrogate is internally generated by the system and is invisible
to the user or application.
和Natural vs Surrogate.关于在两者之间进行选择的讨论.
回到你的模型,按照独立性递减的顺序列出:
CREATE TABLE `groups` (
`groupId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,PRIMARY KEY (`groupId`)
) ENGINE=InnoDB;
CREATE TABLE `domains` (
`domainId` int(10) unsigned NOT NULL AUTO_INCREMENT,`groupId` int(10) unsigned NOT NULL,`someOtherData` varchar(32) DEFAULT NULL,KEY `key_domains_groupId` (`groupId`),CONSTRAINT `fk_domains_groups` FOREIGN KEY (`groupId`) REFERENCES `groups` (`groupId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `users` (
`userId` int(10) unsigned NOT NULL AUTO_INCREMENT,`domainId` int(10) unsigned NOT NULL,`someData` varchar(32) DEFAULT NULL,CONSTRAINT `fk_users_domains` FOREIGN KEY (`groupId`,CONSTRAINT `fk_users_groups` FOREIGN KEY (`groupId`) REFERENCES `groups` (`groupId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
一些划痕工作:
truncate table groups; -- disallowed
delete from groups;
alter table groups auto_increment 1; -- reset,after running delete from.
insert groups(someMoreData) values ('group0001'),('group0002');
select * from groups;
insert domains(groupId,someOtherData) values
(1,'sod'),(1,(2,'sod');
select * from domains; -- AI 1 to 5 above
insert users(groupId,domainId,someData) values (1,1,'sd'); -- success
insert users(groupId,3,4,'sd'); -- Error 1452 fk failure
很明显,用户并不真正需要复合FK到域中.相反,它只需要一个列FK进入域的替代AI PK.这足以完成与你正在做的相同的效果.
与此一致,users.domainId就足够了,users.groupId引入了非规范化,后者应该被丢弃.
无论如何,希望这是有帮助的.