首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >映射与DQL

映射与DQL
EN

Stack Overflow用户
提问于 2013-05-03 22:51:14
回答 2查看 246关注 0票数 2

我有3张桌子-用户、区域和联系人。联系人可以属于用户或区域。用户可以属于许多领域。

我想要提取属于用户的所有联系人(如DB中明确定义的),以及属于与用户相同区域的所有联系人。

我可以看到我的数据库映射和我需要用DQL编写的查询来得到我想要的东西吗?我在数据库映射中做错什么了吗?

我绝对是一个SQL用户,能够轻松地在普通SQL中获取我想要的东西。在普通SQL中,下面是我想要做的事情:

代码语言:javascript
复制
 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);

用户

代码语言:javascript
复制
/**
 * @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;

联系人

代码语言:javascript
复制
/**
 * @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;

面积

代码语言:javascript
复制
/**
 * @ORM\ManyToMany(targetEntity="User", mappedBy="users")
 */
private $users;

/**
 * @ORM\OneToMany(targetEntity="Contact", mappedBy="area")
 */
private $contacts;

我遇到的主要问题是,DQL确实希望您查询一个对象,而在SQL中查询用户/区域关系表就更容易了。我试图编写一个查询,该查询从联系人中提取区域,然后从联系人中提取用户,然后从区域中提取用户,但我得到了一个错误消息,即“用户”不是区域对象中定义的索引。再说一次,我是个理论新手,所以我可能做错了什么。

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

代码语言:javascript
复制
    $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());
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-24 04:10:40

应该有人打我耳光,因为我提供了先前的答案。虽然它完成了工作,我是完全正确的,它没有优化。使用该方法的查询需要3秒才能往返于数据库(3秒!)。很明显,在我的世界里还有很多其他的事情,把性能作为完成这件事的必要条件,但是事情已经改变了。我设法将这个查询分解成两个较小的(Doctrine生成的)查询,每个查询可能需要0.2或0.3s。

代码语言:javascript
复制
    $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()来添加一个数据库查询(如果Doctrine还没有这些信息),但是这段代码使用query表达式的效果要好得多(0.3s对3s是原始查询时间的10%!)

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

希望这个更新到一个8个月前的问题帮助别人!

票数 1
EN

Stack Overflow用户

发布于 2013-05-04 18:51:54

因此,您无法在DQL中获取对象的对象。我需要获取所有“Area”(“Contact”的对象),然后获取该区域的所有“用户”。

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

代码语言:javascript
复制
$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());

从Doctrine生成的SQL看起来并不是特别优化,但它完成了任务。如果有人想让Doctrine更好地优化下面的查询,我很想听听大家的意见。

选择m0_.id为id0,m0_.name为name1,m0_.email为email2,m0_.media_area_id为media_area_id3,m0_.user_id为user_id4,联系人m0_左连接用户u1_ ON m0_.user_id = u1_.id左侧联接区域m2_ ON m0_.area_id = m2_.id,用户m2_左加入m0_.user_id=en19# ON =左侧联接区域ON =?或(m4_.id = m2_.id和u3_.id =?);

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16368644

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档