如何在没有连接列的情况下映射一对一关系(实体通过其 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_regulation 和 financial_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;
}
在我的工作中,我试图将遗留数据库方案与 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_regulation 和 financial_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;
}