如何在没有连接列的情况下映射一对一关系(实体通过它们的 ID 连接)?
Posted
技术标签:
【中文标题】如何在没有连接列的情况下映射一对一关系(实体通过它们的 ID 连接)?【英文标题】:How to map one-to-one relation without join column (entities are joined via their IDs)? 【发布时间】: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_regulation 和 financial_reporter 继承自该表。为了解决这个问题,我使用了class table inheritance,它工作正常。
问题在于 global_register_item 和 article 之间的关系。它是一对一的关系,通过它们的 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_regulation
或global_register_item
和article
之间的关系究竟存储在哪一列?我在您的问题中的任何地方都没有看到加入列。
您是否只是尝试使用new account 编辑您的问题?
@NicolaiFröhlich 据我了解,article
只是一个可空的OneToOne
到global_register_item
,其中连接列是两个表上的id
,article
的标识符为输入NONE
。
@msg 你对情况的理解是对的。为了更好地解释,我添加了一些代码和“数据”。
【参考方案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_item 和 article
创建视图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;
我认为这远非最佳,但这是我能想到的最佳解决方案。
【讨论】:
以上是关于如何在没有连接列的情况下映射一对一关系(实体通过它们的 ID 连接)?的主要内容,如果未能解决你的问题,请参考以下文章
JPA PessimisticLockScope.NORMAL并锁定“关系”