2012-07-11 83 views
3

我最近读Doctrine 2's best practices,并通过该停止:什么时候Doctrine 2使用组合键发生错误?

25.3。避免使用复合键
尽管Doctrine完全支持复合键,但最好不要在可能的情况下使用它们。复合键 需要由Doctrine额外的工作,因此有更高的错误概率 。

我不明白的是:如果"Doctrine fully supports composite keys",它在处理这些键时怎么会出错?

所以我想问一下这个问题作为一个社会的维基,希望这将有助于我们了解什么是"probability of errors"

你有例子来共享示情况下,你已经遇到了由此​​不处理复合键很好/因为它应该?

回答

3

至于我,我相信我已经遇到了一些问题,一个非常基本的数据库架构包含其主键由2个外键的表:

enter image description here

当我产生我的模型,对应于product_i18n实体企业未建立

$ php doctrine-module.php orm:convert-mapping --namespace="Dbi\Entity\\" \ 
--from-database --force annotation module/Dbi/src/ 
Processing entity "Dbi\Entity\Locale" 
Processing entity "Dbi\Entity\Product" 

$ php doctrine-module.php orm:generate-entities --generate-annotations=1 \ 
module/Dbi/src 
Processing entity "Dbi\Entity\Locale" 
Processing entity "Dbi\Entity\Product" 

然而,我相信我的database schema正确创建:

PRIMARY KEY (`product_id`, `locale_id`) , 
    INDEX `fk_product_i18n_locale` (`locale_id` ASC) , 
    INDEX `fk_product_i18n_product` (`product_id` ASC) , 
    CONSTRAINT `fk_product_i18n_locale` 
    FOREIGN KEY (`locale_id`) 
    REFERENCES `mydb`.`locale` (`id`), 
    CONSTRAINT `fk_product_i18n_product` 
    FOREIGN KEY (`product_id`) 
    REFERENCES `mydb`.`product` (`id`) 

此外,​​的Schema Manager表明学说似乎明白了这层关系完全(var_dump输出改变,以使其更简洁:删除的东西,如arrayRECURSIONstring ...) :

$em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default'); 
$sm = $em->getConnection()->getSchemaManager(); 
var_dump($sm->->listTables()); 

object(Doctrine\DBAL\Schema\Table)#290 (10) { 
["_name":protected]=> "product_i18n" 

["_indexes":protected]=> 
    ["primary"]=> 
    ["_columns":protected]=> 
     [0]=> "product_id" 
     [1]=> "locale_id" 

["_fkConstraints":protected]=> 
    ["fk_product_i18n_locale"]=> 
    object(Doctrine\DBAL\Schema\ForeignKeyConstraint)#285 (9) { 
    ["_localColumnNames":protected]=> "locale_id" 
    ["_foreignTableName":protected]=> "locale" 
    ["_foreignColumnNames":protected]=> "id" 

    ["fk_product_i18n_product"]=> 
    object(Doctrine\DBAL\Schema\ForeignKeyConstraint)#286 (9) { 
    ["_localColumnNames":protected]=> "product_id" 
    ["_foreignTableName":protected]=> "product" 
    ["_foreignColumnNames":protected]=> "id" 

所以我在一个情况,即我可以查询的product_i18n表的模式,但由于没有产生相应的实体模型无法与该表进行交互。

UPDATE:user1136666指出:known issues and limitations page颂声明如下:

虽然我们声明,我们支持复合主键不 目前包括外键作为主键列。

解决方法是定义一个代理键和外键添加唯一约束,就像这样:

CREATE TABLE IF NOT EXISTS `mydb`.`product_i18n` (
    `id` INT NOT NULL AUTO_INCREMENT , 
    `name` VARCHAR(45) NULL , 
    `description` TEXT NULL , 
    `created_at` DATETIME NULL , 
    `modified_at` DATETIME NULL , 
    `product_id` INT NOT NULL , 
    `locale_id` INT NOT NULL , 
    INDEX `fk_product_i18n_locale` (`locale_id` ASC) , 
    INDEX `fk_product_i18n_product` (`product_id` ASC) , 
    PRIMARY KEY (`id`) , 
    UNIQUE (`locale_id` , `product_id`), 
    CONSTRAINT `fk_product_i18n_locale` 
    FOREIGN KEY (`locale_id`) 
    REFERENCES `mydb`.`locale` (`id`) 
    CONSTRAINT `fk_product_i18n_product` 
    FOREIGN KEY (`product_id`) 
    REFERENCES `mydb`.`product` (`id`) 
ENGINE = InnoDB; 

功能要求:http://www.doctrine-project.org/jira/browse/DDC-1926

2

上表product_i18n的问题是它没有主键。请尝试将product_idlocale_id设置为复合主键。 Doctrine 2将生成实体。主键是学说2实体所必需的。

+0

不,它不会:'PRIMARY KEY(\'product_id \',\'locale_id \')'? – Max 2012-07-11 21:02:13

+0

对不起,我没有看到他们。我认为真正的问题是使用主键作为外键。我尝试不使用他们作为外键,他们工作! 请检查这里 http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/limitations-and-known-issues.html 这种情况下仍然在Doctrine 2的限制。 – 2012-07-13 22:51:14

+0

事实上,创建代理键作为主键代替了由外键组成的主键,从而解决了问题。 – Max 2012-07-14 09:13:24