4

考虑下图: 在此处输入图像描述

在 aUser有多个BlogPost的情况下,anEventBlogPost具有 的属性的类型Venue

我有以下实体类:

**
 * @ORM\Entity()
 * @ORM\Table(name="User")
 */
class User {
    ...
    /**
     * @ORM\OneToMany(targetEntity="BlogPost",mappedBy="User")
     * @ORM\JoinColumn(...)
     */
    protected $BlogPosts;
    ...
}

/**
 * @ORM\Entity()
 * @ORM\Table(name="BlogPost")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(...)
 * @ORM\DiscriminatorMap({...})
 * ...
 */
class BlogPost {
    ...
    /**
     * @ORM\ManyToOne(targetEntity="User",inversedBy="BlogPosts")
     * @ORM\JoinColumn(...)
     */
    protected $User
    ...
}

/**
 * @ORM\Entity()
 * @ORM\Table(name="Event")
 */
class Event extends BlogPost {
    ...
    /**
     * @ORM\ManyToOne(targetEntity="Venue")
     * @ORM\JoinColumn(...)
     */
    protected $Venue;
    ...
}

/**
 * @ORM\Entity()
 * @ORM\Table(name="Venue")
 */
class Venue {
    ...
}

我现在想构建一个查询来获取给定的用户事件并急切地加载事件场所。我得到的最接近的是:

$qb = $em->createQueryBuilder();
$qb
    ->select('User,'BlogPost,Venue')
    ->from('User','User')
    ->join('User.BlogPosts','BlogPost','WITH','BlogPost INSTANCE OF :Event')
    ->join('BlogPost.Venue','Venue')
    ->setParameter('Event',$em->getClassMetadata('Event'));

这给了我一个相当可预测的错误:

Error: Class BlogPost has no association named Venue

删除对VenueI 的引用会让所有 users 都Event很好,但是我将不得不依赖延迟加载来获取Event's 的其余属性。

我已经看到了我映射Events的建议User

class User {
    ...
    /**
     * @ORM\OneToMany(targetEntity="BlogPost",mappedBy="User")
     * @ORM\JoinColumn(name="UserID", referenceColumnName="UserID")
     */
    protected $BlogPosts;

    /**
     * @ORM\OneToMany(targetEntity="Event",mappedBy="User")
     * @ORM\JoinColumn(name="UserID", referenceColumnName="UserID")
     */
    protected $Events;
    ...
}

尝试这样做时,生成的 SQL 会尝试执行以下操作:

SELECT * FROM User 
JOIN Event ON User.id = Event.user_id
JOIN BlogPost ON BlogPost.id = Event.blog_post_id

列在哪里而不是user_id列在哪里,因此出现以下错误:BlogPostEvent

Invalid column name 'user_id'

我应该如何映射类表继承引用?正如我所描述的,有没有办法实现急切加载?

我知道我已经从类、它们的映射和生成的 SQL 中省略了一些细节。如果某些细节有助于深入了解这一点,请大喊大叫。

编辑

这不同于具有多对一关系的单表继承 (STI)作为类表继承而不是单表继承。此外,我对子类的属性的细节感兴趣,想象一下在那个例子中Video是否有额外的参考。

4

1 回答 1

0

我找到了一种方法可以满足我的要求,但我确信一定有更好的方法。

首先编写一个原生查询:

$sql =<<<SQL
SELECT * FROM User user
JOIN BlogPost blog_post ON user.id = blog_post.UserID
JOIN Event event ON blog_post.id = event.BlogPostID
JOIN Venue venue ON event.VenueID = venue.id
WHERE user.id = ?
SQL;

这可以直接运行,也可以$em->getConnection()->prepare()更好地使用 ResultSetMapping 然后通过$em->createNativeQuery($sql,$rsm)

$rsm = new \Doctrine\ORM\Query\ResultSetMappingBuilder($em);
$rsm->addRootEntityFromClassMetadata('User','user');
$rsm->addIndexBy('user','id');
$rsm->addJoinedEntityResult('event','event','user','BlogPosts');
$rsm->addJoinedEntityResult('venue','venue','event','Venue');
$rsm->addFieldResult(); // add all of the fields you are interested in

$query = $this->get_manager()->createNativeQuery($sql,$rsm);
$query->setParameter(1, $user_id);

return $query->getResult($hydration_mode);

这似乎很遗憾,QueryBuilder但据我所知,这是实现这一目标的唯一方法。我很乐意以其他方式展示。

于 2016-01-06T15:20:14.097 回答