我有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中的User对象进行查询的尝试:
$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());发布于 2014-01-24 04:10:40
应该有人打我耳光,因为我提供了先前的答案。虽然它完成了工作,我是完全正确的,它没有优化。使用该方法的查询需要3秒才能往返于数据库(3秒!)。很明显,在我的世界里还有很多其他的事情,把性能作为完成这件事的必要条件,但是事情已经改变了。我设法将这个查询分解成两个较小的(Doctrine生成的)查询,每个查询可能需要0.2或0.3s。
$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个月前的问题帮助别人!
发布于 2013-05-04 18:51:54
因此,您无法在DQL中获取对象的对象。我需要获取所有“Area”(“Contact”的对象),然后获取该区域的所有“用户”。
在DQL中,您可以指定多个"from()“助手方法,这就是我完成工作所需要的。
$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 =?);
https://stackoverflow.com/questions/16368644
复制相似问题