具有ManyToMany关系的Doctrine2中此SQL语句的DQL

时间:2014-11-04 03:01:22

标签: php symfony doctrine-orm doctrine dql

我已经进行了这个SQL查询,以便从数据库中获取所需的数据,并且它可以正常工作:

SELECT DISTINCT ofreg.nombre as oficina 
  FROM nomencladores.oficina_regional AS ofreg  
  LEFT JOIN negocio.solicitud_usuario_oficina_regional AS solusofreg
    ON (ofreg.id = solusofreg.oficina_regional_id)
  JOIN nomencladores.tipo_tramite tram
    ON (tram.id = solusofreg.tipo_tramite_id)
  WHERE (tram.id = 1);

由于我的关系不会在第三个表上生成任何额外的字段,所以我决定在我的实体上进行正确的注释,看看:

class TipoTramite
{
    use IdentifierAutogeneratedEntityTrait;
    use NamedEntityTrait;
    use ActiveEntityTrait;

    /**
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\OficinaRegional", inversedBy="tipoTramites", cascade={"persist"})
     * @ORM\JoinTable(name="negocio.solicitud_usuario_oficina_regional", schema="negocio",
     *      joinColumns={@ORM\JoinColumn(name="oficina_regional_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="tipo_tramite_id", referencedColumnName="id")}
     * )
     */
    protected $oficinaRegionals;
}

class OficinaRegional
{
    use IdentifierAutogeneratedEntityTrait;
    use NamedEntityTrait;
    use ActiveEntityTrait;

    /**
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\TipoTramite", mappedBy="oficinaRegionals", cascade={"persist"})
     */
    protected $tipoTramites;
}

拥有这些实体并假设它们是正确的(如果我错了,请纠正我)我需要编写一个满足上述SQL代码的DQL,能不能给我一些帮助来编写这个DQL?

我总是拥有一个中介实体,但这个案例对我来说是全新的。作为和补充,我知道一个关于此的解决方法,并将在数据库级别创建view并仅使用set方法仅为get方法为该视图编写实体,因为将是只读实体,但我不知道是否是正确的道路,我真的很想学习如何使用ManyToMany(在我的项目中,我有很多这种类型的关系,所以我确定'我会在不久的将来稍后需要这个帮助。)

更新

好的,我想继续关注这个问题而我正在做一些测试,但没有任何有用的结果,这是我的尝试:

第一种方法

public function filtrarOficinaRegionalPorTramite($tramite)
{
    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb
        ->select('ofr.nombre AS oficinaRegional, ttr.nombre as tipoTramite')
        ->from("AppBundle:OficinaRegional", "ofr")
        ->where("ofr.activo = :activo")
        ->leftJoin("AppBundle:TipoTramite", "ttr");

    $qb->setParameter('activo', TRUE);

    if ($tramite != NULL) {
        $qb->andWhere('ttr.id = :tramite');
        $qb->setParameter('tramite', $tramite);
    }

    echo $qb->getQuery()->getSQL();
    return $qb->getQuery()->getResult();
}

由于上一代码中的结果SQL是这样的,所以没有工作:

SELECT n0_.nombre AS nombre0, n1_.nombre AS nombre1 
FROM nomencladores.oficina_regional n0_ 
LEFT JOIN nomencladores.tipo_tramite n1_ 
 ON (n0_.activo = ?) 

第二种方法

public function filtrarOficinaRegionalPorTramite($tramite)
{
    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb
        ->select('ofr.nombre AS oficinaRegional, ttr.nombre as tipoTramite')
        ->from("OficinaRegional ofr")
        ->where("ofr.activo = :activo")
        ->leftJoin('ofr.TipoTramite ttr');

    $qb->setParameter('tramite', $tramite);

    if ($tramite != NULL) {
        $qb->where('ttr.id = :tramite');
        $qb->setParameter('tramite', $tramite);
    }

    return $qb->getQuery()->getResult();
}

但得到了这个错误:

  

警告:缺少Doctrine \ ORM \ QueryBuilder :: from()的参数2,   呼唤   /var/www/html/project.dev/src/AppBundle/Entity/Repository/RegionalOfficeRepository.php   在第25行并在中定义   /var/www/html/project.dev/vendor/doctrine/orm/lib/Doctrine/ORM/QueryBuilder.php   第721行

第三种方法

经过大量时间试图让事情发挥作用后,我仍然遇到问题,但这次我更接近解决问题。所以,这是我的最新镜头,使用此代码:

public function filtrarOficinaRegionalPorTramite($tramite)
{
    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb
        ->select('ofr.nombre AS oficinaRegional, ttr.nombre as tipoTramite')
        ->distinct()
        ->from("AppBundle:OficinaRegional", "ofr")
        ->where("ofr.activo = :activo")
        ->leftJoin("ofr.tipoTramites", "ttr");

    $qb->setParameter("tramite", $tramite);

    if ($tramite != NULL) {
        $qb->andWhere("ttr.id = :tramite");
        $qb->setParameter("tramite", $tramite);
    }

    echo $qb->getQuery()->getSQL();
    return $qb->getQuery()->getResult();
}

我得到了这个SQL:

SELECT DISTINCT n0_.nombre AS nombre0,
                n1_.nombre AS nombre1
FROM nomencladores.oficina_regional n0_
  LEFT JOIN negocio.solicitud_usuario_oficina_regional n2_ ON n0_.id = n2_.tipo_tramite_id
  LEFT JOIN nomencladores.tipo_tramite n1_ ON n1_.id = n2_.oficina_regional_id
WHERE n0_.activo = ?
      AND n1_.id = ?;

根本没有错,但最终的SQL应该是这样的:

SELECT DISTINCT n0_.nombre AS nombre0,
                n1_.nombre AS nombre1
FROM nomencladores.oficina_regional n0_
  LEFT JOIN negocio.solicitud_usuario_oficina_regional n2_ ON n0_.id = n2_.oficina_regional_id
  LEFT JOIN nomencladores.tipo_tramite n1_ ON n1_.id = n2_.tipo_tramite_id
WHERE n0_.activo = TRUE
      AND n1_.id = 1;

我做错了什么?

1 个答案:

答案 0 :(得分:1)

看起来你的连接列映射对于TipoTramite是不正确的,尝试翻转它们。

 /**
 * @ORM\ManyToMany(targetEntity="AppBundle\Entity\OficinaRegional", inversedBy="tipoTramites", cascade={"persist"})
 * @ORM\JoinTable(name="negocio.solicitud_usuario_oficina_regional", schema="negocio",
 *      joinColumns={@ORM\JoinColumn(name="tipo_tramite_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="oficina_regional_id", referencedColumnName="id")}
 * )
 */

http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#one-to-many-unidirectional-with-join-table

至于问号,这些只是稍后会填写的参数。