【问题标题】:Doctrine 2 association without foreign key constraints没有外键约束的 Doctrine 2 关联
【发布时间】:2012-04-08 15:03:16
【问题描述】:

我正在将遗留的 PHP 应用程序转换为 Symfony 2。目前应用程序数据不是很一致,所以我想避免创建外键约束。我的“产品”实体类中有以下注释:

class Product {

  // some definitions

  /**
   * @ORM\ManyToOne(targetEntity="Manufacturer")
   * @ORM\JoinColumn(name="manufacturer_id", referencedColumnName="id" )
   */
  private $Manufacturer;
}

当我执行app/console doctrine:schema:update 时,我得到了 SQL 命令

 ALTER TABLE products ADD CONSTRAINT FK_F6FA18741C3BF575 
   FOREIGN KEY (manufacturer_id) REFERENCES manufacturer(id);

我怎样才能避免这种情况?

【问题讨论】:

    标签: php database symfony doctrine-orm


    【解决方案1】:

    我最近不得不经历同样的过程,幸运的是有一个简单的解决方案,只需在列的注释中添加nullable=true

    只要现有数据有效,这将起作用,在我的情况下,我必须将 0 更改为 NULL,并将不再存在的键更改为 NULL。

    【讨论】:

    • 我已将其添加到我的JoinColumn 注释中,但仍在创建外键约束。
    • 与@flu 相同 - 不走运,反正正在创建外键
    • 从那时起我就没有使用过 Doctrine,但是您确定它是正在创建还是已经存在并且没有被删除。
    • 如果我试图通过命令行使用doctrine2来生成多对多关系表,这对我不起作用。作为替代方案,我使用了一个查询来检测数据库中的所有外键并删除它们 (stackoverflow.com/a/27481326/1153885)
    • 来强化这个答案 - 对于无论如何创建外键并且架构更新失败的情况 - 那是因为您的架构已部分更新并且填充了无效的连接 ID。检查您的连接表db 并通过删除可能包含 0 而不是 NULL 的添加列来恢复,然后在将 nullable=true 添加到连接列注释后重新运行模式更新。仍然会创建外键,但不会失败,因为不会有无效值。
    【解决方案2】:

    基本上你不能阻止生成 sql 命令。至少在不深入研究 Doctrine 代码的情况下是这样。

    但是,您不需要将约束实际应用于您的数据库。没有它们,D2 也能正常工作。

    【讨论】:

    • 是的,但是我不能再使用命令app/console doctrine:schema:update --force,因为更新会在尝试执行 FK 约束时停止。
    • 这个答案与@Pier-Luc-Gendreau 的答案相结合,为我解决了问题。如果你想让 Doctrine2 管理你的数据库关系,那么你需要从丢失的关系中清理你的数据,然后你可以创建丢失的约束。
    【解决方案3】:

    您应该省略 ManyToMany 和 JoinColumn 定义,并使用扩展自动生成的产品存储库的公共 getManufacturer 方法处理自定义产品存储库中的制造商属性。

    【讨论】:

      【解决方案4】:

      我在使用相同的命令时遇到了问题。我得到了例外:

      SQLSTATE[HY000]: 一般错误: 1005 Can't create table 'xxx.#sql-66c_3e' (errno: 150)

      对我来说,将列声明为唯一(在您的案例 ID 中)很有帮助。

      现在app/console doctrine:schema:update 再次运行良好。

      【讨论】:

        【解决方案5】:

        你必须将丢失的外键设置为空,然后你可以设置你的约束。以下查询为您提供要更改的数据集中的 ID:

        select p.id from product p
        left join manufacturer m on m.id=p.manufakturer_id
        where m.id is null
        

        【讨论】:

          【解决方案6】:

          尝试添加 onDelete="CASCADE" 之类的

          * @ORM\JoinColumn(name="manufacturer_id", referencedColumnName="id", onDelete="CASCADE")
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-01-14
            • 2019-04-26
            • 1970-01-01
            • 1970-01-01
            • 2017-10-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多