【问题标题】:How to map one-to-one relation without join column (entities are joined via their IDs)?如何在没有连接列的情况下映射一对一关系(实体通过它们的 ID 连接)?
【发布时间】:2019-12-31 10:45:50
【问题描述】:

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

表 - 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

表格 - 文章

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

表格 - law_regulation

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

表格 - 财务报告者

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

所以 global_register_item 是父表,law_regulationfinancial_reporter 继承自该表。为了解决这个问题,我使用了class table inheritance,它工作正常。

问题在于 global_register_itemarticle 之间的关系。它是一对一的关系,通过它们的 ID 列进行连接(如果 global_register_item 中有与 article 相关的记录,则 中有记录>article 表具有相同的 ID)。但是global_register_item中的一些记录在article中没有记录。有什么办法可以将这种关系与 Doctrine 映射起来?

编辑 1

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

类 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;
}

课堂文章

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;
}

集体法规定

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

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

类财务报告员

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

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

【问题讨论】:

  • 具体的问题是什么? DTYPE 列有时是 null 有时是 "article" 但您仍想将其用作鉴别器列吗?我理解正确吗?请解释一下“global_register_item中的一些记录在文章中没有记录”部分。
  • law_regulationglobal_register_itemarticle 之间的关系究竟存储在哪一列?我在您的问题中的任何地方都没有看到加入列。
  • 您是否只是尝试使用new account 编辑您的问题?
  • @NicolaiFröhlich 据我了解,article 只是一个可空的OneToOneglobal_register_item,其中连接列是两个表上的idarticle 的标识符为输入NONE
  • @msg 你对情况的理解是对的。为了更好地解释,我添加了一些代码和“数据”。

标签: php orm doctrine-orm doctrine mapping


【解决方案1】:

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

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

并在您的 GlobalRegisterItem 类中引用它:

 /**
  * 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;
 }

【讨论】:

    【解决方案2】:

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

    global_register_itemarticle

    创建视图
    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
    

    类 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;
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-23
      • 2013-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-28
      • 2021-03-15
      • 2020-09-18
      相关资源
      最近更新 更多