我正在使用遗留数据库(这意味着没有模式更改!),我需要创建所涉及的Doctrine实体之间的关联。我将首先描述数据结构,然后解释我所尝试的。抽象主义关联映射无鉴别器(遗留数据库)
该数据库有一个用户表与其他各种表也存储用户相关的信息。例如:
siteUser
有:
- 内容识别(PK)
- 的firstName
- lastName的
- 用户名
- 密码
- ...
和siteUser
个实体在该系统中它是沿的线的元数据:
- metadataId(PK)
- 标题
- 描述
- 关键字
- CREATEDATE
- publishDate
- 内容识别
- contentTable(鉴别器)
- ...
几乎所有的数据库可以通过存储它在metadata.contentId
野外PK,并在metadata.contentTable
字段的表名有元数据。请注意,metadata.contentId
不是外键,因为我还没有看到它们,所以这些对于DBA来说一定是陌生的。
系统上的用户可以保存他们发现的与他们相关的信息,这样他们可以稍后再回到系统,而不必再去寻找相同的信息。
这与所谓的conLink
内容类型,conVideo
,conLeaflet
存储为数据库实体(其中有元数据)来完成。
例如一个conVideo
看起来像这样:
- 内容识别(PK)
- embedCode
用户可以存储标记这个信息作为与他们相关的方法是由系统存储它在一个叫做userSavedContent
的链接表中:
- userSa vedContentId(PK)
- 用户id
- metadataId
注意userSavedContent.userId
和userSavedContent.metadataId
也不是外键约束。
方法!
我需要获取用户保存的内容。在SQL中这是没有问题的!
SELECT
metadata.title,
conVideo.embedCode
FROM
userSavedContent
INNER JOIN
metadata ON userSavedContent.metadataId = metadata.metadataId
INNER JOIN
conVideo ON conVideo.contentId = metadata.contentId
WHERE userSavedContent.userId = 193745
AND metadata.contentTable = 'conVideo'
但是这样做的教义比较复杂,因为metadata.contentTable
值可能是任何conLink
,conVideo
,conLeaflet
实体。
所以我的应用程序是使用Symfony2(和Doctrine)构建的,我有为所有上述实体定义的模型。
在这种Metadata
是一个抽象类与鉴别上metadata.contentTable
:
/**
*
* @ORM\Table(name="metadata")
* @ORM\Entity()
* @ORM\HasLifecycleCallbacks
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="contentTable", type="string")
* @ORM\DiscriminatorMap(
* {
* "conLink" = "MyApp\Bundle\DataApiBundle\Entity\Metadata\ConLinkMetadata",
* "conVideo" = "MyApp\Bundle\DataApiBundle\Entity\Metadata\ConVideoMetadata",
* "siteUser" = "MyApp\Bundle\DataApiBundle\Entity\Metadata\SiteUserMetadata"
* }
*)
*/
abstract class Metadata
的ConVideoMetadata
类扩展Metadata
并增加了一个content
的特性,即ConVideo
实体它关联:
/**
* @var ContentType $content
*
* @ORM\OneToOne(
* targetEntity="MyApp\Bundle\DataApiBundle\Entity\ContentType\ConVideo",
* inversedBy="metadata",
* cascade={"persist", "remove"}
*)
* @ORM\JoinColumn(name="contentId", referencedColumnName="contentId")
*/
protected $content;
现在userSavedContent
实体具有metadata
属性将其关联到元数据项。
/**
* @var Metadata $metadata
*
* @ORM\ManyToOne(
* targetEntity="MyApp\Bundle\DataApiBundle\Entity\Metadata",
* inversedBy="userSavedContent"
*)
* @ORM\JoinColumn(name="id", referencedColumnName="metadataId")
*/
protected $metadata;
最后的siteUser
由下列财产上的实体与userSavedContent
:
/**
* @ORM\OneToMany(
* targetEntity="MyApp\Bundle\DataApiBundle\Entity\UserSavedContent",
* mappedBy="siteUser",
* cascade={"persist", "remove"},
* orphanRemoval=true
*)
* @ORM\JoinColumn(name="contentId", referencedColumnName="userId")
*/
private $userSavedContentItems;
的问题!
在我siteUserRepository
类我现在需要查询的siteUser和所有它保存的内容项:
$builder = $this->createQueryBuilder('s')
->select('s', 'm', 'usc', 'uscm', 'uscc')
->innerJoin('s.metadata', 'm')
->leftJoin('s.userSavedContentItems', 'usc')
->leftJoin('usc.metadata', 'uscm')
->leftJoin('uscm.content', 'uscc');
return $builder;
这不起作用!
"[Semantical Error] Error: Class MyApp\Bundle\DataApiBundle\Entity\Metadata has no association named content"
这使得自MyApp\Bundle\DataApiBundle\Entity\Metadata
当然感觉不具有content
属性,其子MyApp\Bundle\DataApiBundle\Entity\Metadata\ConVideoMetadata
是一个与该关联。我认为教义本来可以解决这个问题,但显然不是。
所以我的问题是:
- 是这种做法非常错误的?如果没有,我可以做些什么来使关联/查询工作?