如何在没有连接列的情况下映射一对一关系(实体通过其 ID 连接)?

How to map one-to-one relation without join column (entities are joined via their IDs)?

在我的工作中,我试图将遗留数据库方案与 Doctrine 进行映射。我无法更改此方案,因为它已被其他公司应用程序使用。这是一个简短的方案概述:

Table - global_register_item

ID | NAME                                      | DTYPE
1  | "global register item with article #1"    | law_regulation
2  | "global register item without article #1" | financial_reporter
3  | "global register item without article #2" | law_regulation
4  | "global register item without article #3" | law_regulation
5  | "global register item with article #2"    | financial_reporter

Table - 文章

ID | SID | other fields which I actually do not need
1  | 89  | ...
5  | 45  | ...

Table - law_regulation

ID | other fields
1  | ...
3  | ...
4  | ...

Table - financial_reporter

ID | other fields
2  | ...
5  | ...

所以 global_register_item 是父级并且 law_regulationfinancial_reporter继承自此table。为了解决这个问题,我使用了 class table inheritance 并且效果很好。

问题是 global_register_item文章 之间的关系。这是一对一的关系,连接是通过它们的 ID 列完成的(如果 global_register_item 中有一条与 article[=56 相关的记录=],在文章table中有一条ID相同的记录)。但是global_register_item中的一些记录在文章中没有记录。有什么方法可以将这种关系映射到 Doctrine 吗?

编辑 1

这是我的 PHP 项目代码。顺便提一句。我只需要阅读记录。我需要将有关 SID 列的信息获取到我的 GlobalRegisterItem 实体。

Class GlobalRegisterItem

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="global_register_item")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="DTYPE", type="string")
 * @ORM\DiscriminatorMap({
 *     "law_regulation" = "App\Entity\LawRegulation",
 *     "financial_reporter" = "App\Entity\FinancialReporter"})
 */
abstract class GlobalRegisterItem
{
    /**
     * @var int
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     */
    private $id;

    /**
     * @var string
     * @ORM\Column(name="name", type="string")
     */
     private $name;

     /**
      * Article|null
      * HOW TO MAP THIS?
      */
     private $article;
}

Class条

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="article")
 */
class Article
{
    /**
     * @var int
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     */
    private $id;

    /**
     * @var int
     * @ORM\Column(name="SID", type="int")
     */
     private $sid;
}

Class 法律法规

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="law_regulation")
 */
class LawRegulation extends GlobalRegisterItem
{
    /** SOME MAPPED FIELDS */
}

Class财经记者

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="law_regulation")
 */
class FinancialReporter extends GlobalRegisterItem
{
    /** SOME MAPPED FIELDS */
}

解决此问题的一种可能方法(如果您只需要读取数据)是:

global_register_item文章

创建视图
SELECT global_register_item.*, article.SID AS `SID`
FROM global_register_item
LEFT JOIN article ON global_register_item.id = article.id

ID | NAME                                      | DTYPE              | SID
1  | "global register item with article #1"    | law_regulation     | 89
2  | "global register item without article #1" | financial_reporter | NULL
3  | "global register item without article #2" | law_regulation     | NULL
4  | "global register item without article #3" | law_regulation     | NULL
5  | "global register item with article #2"    | financial_reporter | 45

Class GlobalRegisterItem

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="global_register_item_view")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="DTYPE", type="string")
 * @ORM\DiscriminatorMap({
 *     "law_regulation" = "App\Entity\LawRegulation",
 *     "financial_reporter" = "App\Entity\FinancialReporter"})
 */
abstract class GlobalRegisterItem
{
    /**
     * @var int
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     */
    private $id;

    /**
     * @var string
     * @ORM\Column(name="name", type="string")
     */
     private $name;

     /**
      * int|null
      * @ORM\Column(name="SID", type="integer")
      */
     private $sid;
}

我认为这远非最佳,但这是我能想到的最佳解决方案。

您可以在 Article 实体中使用 OneToOne bidirectional relation

/**
 * @ORM\OneToOne(targetEntity="GlobalRegisterItem", inversedBy="article")
 * @ORM\JoinColumn(name="id", referencedColumnName="id", nullable=true)
 */
private $item;

并在您的 GlobalRegisterItem class:

中引用它
 /**
  * Article|null
  * @ORM\OneToOne(targetEntity="Article", mappedBy="item")
  */
 private $article;

 /**
  * Gets the sid of the article (if any).
  * @returns int|null
  */
 public function getArticleSid()
 {
   if (null !== $this->article) {
     return $this->article->getSid();
   }
   return null;
 }