2011-12-13 107 views
18

我有一个DQL查询和实体专业化的问题。Doctrine DQL,类表继承和访问子类字段

我有一个实体叫Auction,这是OneToOneItem的关系。 ItemFilmBookmappedSuperclass。我需要一个可以支持搜索引擎的查询,允许用户查找具有不同属性的不同属性AND的拍卖(这是AND部分,使其具有挑战性)。

问题是,即使Auction有一个指向Item的关联,我需要访问FilmBook特定的字段。用户将指定他们正在查找的Item类型,但除了在我的DQL查询中使用INSTANCE OF之外,我没有看到任何使用此信息的方式。

到目前为止,我使用查询像曾尝试:

SELECT a FROM Entities\Auction a 
    INNER JOIN a.item i 
    INNER JOIN i.bookTypes b 
    WHERE i INSTANCE OF Entities\Book 
    AND b.type = 'Fantasy' 
    AND ...". 

这样一个错误的查询结果说:

Entities\Item没有字段或协会命名bookTypes

这是虚假的Book,但真的Item

我也曾尝试

SELECT a FROM Entities\Book i 
    INNER JOIN i.auction a ... 

不过,我想学说规定,我指的是同一个实体在SELECTFROM语句。

如果这很重要,我使用类表继承。尽管如此,我认为切换到单表继承是不可能的。

任何想法?

+0

可能重复[where-ing歧视表](http://stackoverflow.com/questions/14851602/where-ing-in-discriminated-tables) – Ocramius 2014-01-20 05:57:10

回答

9

正如马特所说,这是一个老教义项目不能解决的问题(DDC-16)。

问题是,学说的DQL是一个静态类型的语言,它的内部具有一定的复杂性。

我们考虑过允许多次上传,但努力获得这个工作根本不值得,而且人们会滥用语法做非常危险的事情。

如DDC-16所述,也不可能理解属性属于哪个类而不会产生讨厌的问题,例如多个子类使用不同的列名定义相同的属性。

如果要过滤CTI或JTI中的子类中的数据,可以使用我在https://stackoverflow.com/a/14854067/347063中描述的技术。这会将您的DQL与所有涉及的子类联系起来。

的DQL你需要在你的情况下,最有可能(假设Entities\BookEntities\Item子类):

SELECT 
    a 
FROM 
    Entities\Auction a 
INNER JOIN 
    a.item i 
INNER JOIN 
    i.bookTypes b 
WHERE 
    i.id IN (
     SELECT 
      b.id 
     FROM 
      Entities\Book b 
     WHERE 
      b.type = 'Fantasy' 
    ) 

那是你的问题的伪代码。这并不好,但请记住,SQL和DQL是非常不同的,并遵循不同的规则。

0

我有同样的问题,并没有找到一个解决方案,没有使用每个子类的单独的查询,并稍后在应用程序级别合并它们。

有一点我确定,单表继承不会解决这个问题,完全一样的事情。

还有另一种选择,虽然在逻辑上很脏。 定义超类中的所有字段(您需要的字段)。如果记录逻辑上没有该字段,它将是空的。不是一个漂亮的景象,但嘿,比2-3-4 -...查询更优化。此外,在这种情况下单表继承绝对是更好的方式去

+2

合并结果并不完全如此,因为我从不需要Films和Books同时出现在查询结果中。我终于提出的解决方法是添加拍卖 - 项目关系的反面并查询项目而不是拍卖('SELECT i FROM Entities \ Book INNER JOIN i.auction a WHERE(...)') 。由于我知道我在找哪个子类,所以我可以相应地构建我的查询。但是,感谢你的回复,你的想法可能是一个好的方法,因为在这样的情况下,使用继承与Doctrine似乎没什么意义。 – crizzis 2011-12-26 23:05:11

2

教义团队已经表示,他们不会增加对这种支持:

http://www.doctrine-project.org/jira/browse/DDC-16

中肯的意见从该页面:

这确实很棘手。然而,这种语法本身可以不起作用, ,因为可能有几个子类名为“d”, ,所以教义不会知道你的意思。


我关闭这一个。

这个问题的要求基本上是违反面向对象的原则。

如果你真的需要在您的 继承跨多个孩子的实体进行过滤,然后尝试的东西如下代替:

选择 [R FROM 根r其中 r.id IN( 选择 ℃。 ID FROM Child C级 WHERE c.field =:值 )

2

您可以轻松地解决这个左连接使用的ID与你的继承类的基础机构:

SELECT a FROM Entities\Auction a 
    INNER JOIN a.item i 
    INNER JOIN Entities\Book b WITH b.id = i.id 
    INNER JOIN b.bookTypes bt 
    WHERE bt.type = 'Fantasy' 
    AND... 

或用的QueryBuilder:

$queryBuilderb->select('a') 
    ->from('Entities\Auction', 'a') 
    ->innerJoin('a.item', 'i') 
    ->innerJoin('Entities\Book', 'b', 'WITH', 'b.id = i.id') 
    ->innerJoin('b.bookTypes', 'bt') 
    ->where('bt.type = :type') 
    ->andWhere(... 
    ->setParameter('type', 'Fantasy'); 

这是根据给出的答案由伊恩飞利浦在这个问题here