Symfony 映射与DQL

Symfony 映射与DQL,symfony,orm,doctrine-orm,dql,Symfony,Orm,Doctrine Orm,Dql,我有3个表-用户、区域和联系人。联系人可以属于某个用户或某个区域。一个用户可以属于多个领域 我想提取属于某个用户的所有联系人(如DB中特别定义的),以及与该用户属于同一区域的所有联系人 我可以对我的数据库映射和我需要用DQL编写的查询有一个新的了解吗。我的数据库映射是否出错 我绝对是一个SQL爱好者,能够轻松地用普通SQL获取我想要的东西。在纯SQL中,我要做的是: select c.* from contact c LEFT JOIN user_area ua ON c.area_id=ua

我有3个表-用户、区域和联系人。联系人可以属于某个用户或某个区域。一个用户可以属于多个领域

我想提取属于某个用户的所有联系人(如DB中特别定义的),以及与该用户属于同一区域的所有联系人

我可以对我的数据库映射和我需要用DQL编写的查询有一个新的了解吗。我的数据库映射是否出错

我绝对是一个SQL爱好者,能够轻松地用普通SQL获取我想要的东西。在纯SQL中,我要做的是:

 select c.* from contact c LEFT JOIN user_area ua ON c.area_id=ua.area_id where (ua.user_id=XXX OR c.user_id=XXX);
用户

/**
 * @ORM\ManyToMany(targetEntity="area", inversedBy="areas")
 * @ORM\JoinTable(name="user_area",
 *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="area_id", referencedColumnName="id")}
 *      )
 */
private $areas;

/**
 * @ORM\OneToMany(targetEntity="Contact", mappedBy="user")
 */
private $contacts;
联系方式

/**
 * @ORM\ManyToOne(targetEntity="Area")
 * @ORM\JoinColumn(name="area_id", referencedColumnName="id")
 */
private $area;

/**
 * @ORM\ManyToOne(targetEntity="User", inversedBy="Contacts")
 * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
 */
private $user;
区域

/**
 * @ORM\ManyToMany(targetEntity="User", mappedBy="users")
 */
private $users;

/**
 * @ORM\OneToMany(targetEntity="Contact", mappedBy="area")
 */
private $contacts;
我遇到的主要问题是DQL确实希望您查询一个对象,而在SQL中查询用户/区域关系表以获得我想要的东西显然更容易。我试图编写一个查询,从联系人中提取区域,然后从联系人中提取用户,然后从区域中提取用户,但我收到一条错误消息,“用户”不是我的区域对象中定义的索引。再说一遍,我是个信条新手,所以我可能做错了什么

下面是我尝试从Symfony中的用户对象进行的查询:

    $qb = $em->createQueryBuilder()
        ->addSelect('c')
        ->from('MyBundle:Contact', 'c')
        ->leftJoin('c.area', 'ca')
        ->leftJoin('c.user', 'cu')
        ->leftJoin('ca.users', 'cau')
        ->add('where', 'c.user = ?1 OR cau.id = ?1')
        ->add('orderBy', 'c.name')
        ->setParameter(1, $this->getId());

因此,事实证明,您无法在DQL中获取对象的对象。我需要获取所有“区域”(联系人的对象),然后获取该区域的所有“用户”

在DQL中,可以指定多个“from()”helper方法,这就是我完成工作所需要的

$qb = $em->createQueryBuilder()
    ->addSelect('c')
    ->from('MyBundle:Contact', 'c')
    ->from('MyBundle:User', 'u')
    ->leftJoin('c.area', 'ca')
    ->leftJoin('c.user', 'cu')
    ->leftJoin('u.areas', 'ua')
    ->add('where', 'c.user = ?1 OR (ua.id=ca.id AND u.id = ?1')
    ->add('orderBy', 'c.name')
    ->setParameter(1, $this->getId());
从条令生成的SQL看起来并没有特别优化,但它完成了任务。如果有人想让条令更好地优化下面的查询,我很乐意听取意见

1.1.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.媒体和2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2=?或者(m4_u0.id=m2_0.id和u3_0.id=?)


有人应该打我一巴掌,因为我提供了之前的答案。虽然它完成了任务,但我绝对正确,它没有优化。使用该方法的查询需要3秒钟才能返回到数据库(3秒钟!)。很明显,在我的世界里还有很多其他的事情要做,这些事情都把性能作为完成任务的必要条件,但事情已经改变了。我设法将这个查询分解为两个较小的(条令生成的)查询,每个查询可能需要0.2或0.3秒

    $areas = $user->getAreas();

    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb->select('c')
        ->from('MyBundle:Contact', 'c')
        ->where($qb->expr()->in('c.area', '?1'))
        ->orWhere('c.user = ?2')
        ->setParameter(1, $areas->toArray())
        ->setParameter(2, $user);
    $query = $qb->getQuery();
    $result = $query->getResult();
    return $result;
事实上,我必须调用
$user->getAreas()
添加了一个数据库查询(如果Dority还没有该信息),但是使用查询生成器表达式的代码工作得更好(0.3s与3s是原始查询时间的10%)

我认为我当时缺少的主要概念是,查询生成器希望处理您的对象(实体)以及您在实体中定义的属性。我有很强的SQL背景,并且知道我希望Doctrine生成的特定SQL查询,因此没有正确地处理这个问题


希望对一个8个月前的问题的更新对某人有所帮助

$qb=$em->createQueryBuilder('c')设置根选择别名,因此不需要添加选择。另外,我认为你不需要第三次加入。你可以只使用PDO,而不必使用doctorine。既然你没有obhects,那又有什么意义呢anyway@Lighthart如果我排除了第三个连接(因此也从WHERE子句中删除了cau.id),那么我只剩下用户“拥有”的所有联系人。没有错误,但我还想提取所有联系人,这些联系人与用户所属的所有区域具有相同的区域。不过,谢谢你的建议。你应该通过获取的实体来获取这些关系。原则:获取实体,而不是元组。