Doctrine 2连接表,ManyToOne单向,其中tbl2.value =:value

时间:2018-04-04 19:10:22

标签: php doctrine-orm

我试图弄清楚如何连接两个表,同时查询第二个表。我觉得它很简单:

// Within ServerServiceRepository 
return $this->createQueryBuilder('ss')
    ->join(ServiceType::class, 't')
    ->where('t.serviceTypeName = :name')
    ->getQuery()
    ->execute(['name' => $name]);

但事实证明,并非如此......

问题是查询没有加入密钥(两个表上的service_type_id)。这里发生了什么?我正确设置了所有OneToMany关系:

/**
 * ServerService
 *
 * @ORM\Table(name="server_services")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ServerServiceRepository")
 */
class ServerService extends AbstractEntity
{
    /**
     * @var ServiceType
     *
     * @ORM\Column(name="service_type_id", type="integer", nullable=false)
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Supportal\ServiceType", fetch="LAZY", inversedBy="serviceTypeId")
     * @ORM\JoinColumn(name="service_type_id", referencedColumnName="service_type_id")
     */
    private $serviceType;
    // [...]
 }

/**
 * ServiceType
 *
 * @ORM\Table(name="service_types")
 * @ORM\Entity
 */
class ServiceType extends \AppBundle\Entity\AbstractEntity
{
    /**
     * @var integer
     *
     * @ORM\Column(name="service_type_id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\ServerService", fetch="EXTRA_LAZY", mappedBy="serviceType")
     */
    private $serviceTypeId;

    /**
     * @var string
     *
     * @ORM\Column(name="service_type_name", type="string", length=255, nullable=true)
     */
    private $serviceTypeName;
    // [...]

}

我已将ServiceT中的OneToMany关系添加/删除为无更改。这实际上是一个单向关系。根据Doc Doctrine自己的文档(第5章),ServerType 需要关系映射。

SQL查询正在生成缺少实际密钥的JOIN:

INNER JOIN service_types s1_ ON (s1_.service_type_name = ?)

为了让这项工作正常,我在学说中缺少什么?我看过这些教程。 Symofny的例子几乎就是我所追求的,除了我需要选择"类别名称"不是产品ID:https://symfony.com/doc/2.8/doctrine/associations.html

我必须错过一些非常简单的东西。但我不能为我的生活而盯住它......

修改

我已在代码中从ServiceType中删除了OneToMany。它是可选的。反正不需要这个。这是单向关系。

我试过这个:

    return $this->createQueryBuilder('ss')
        ->join('ss.serviceType', 't')
        ->where('t.serviceTypeName = :name')
        ->getQuery()
        ->execute(['name' => $name]);

导致此错误:

[Semantical Error] line 0, col 85 near 't WHERE t.serviceTypeName': Error: Class AppBundle\Entity\ServerService has no association named serviceType

解决方案

解决方案是删除@ORM Column定义。看起来它是关系定义中的冲突。

1 个答案:

答案 0 :(得分:0)

首先,将 ManyToOne docblock定义更改为:

 /**
 * @var ServiceType
 *
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Supportal\ServiceType", fetch="LAZY", inversedBy="serverService")
 * @ORM\JoinColumn(name="service_type_id", referencedColumnName="service_type_id")
 */
private $serviceType;

同时更改OneToMany,删除第@ORM\OneToMany(targetEntity="AppBundle\Entity\ServerService", fetch="EXTRA_LAZY", mappedBy="serviceType")

为OneToMany关系创建新字段 serverService

/**
 * 
 * @ORM\OneToMany(targetEntity="ServerService", mappedBy="serviceType")
 */
private $serverService;

您应加入关系字段,在本例中为 serviceType 。您定义连接的方式就像选择两个表一样。

更改为:

return $this->createQueryBuilder('ss')
    ->join('ss.serviceType', 't')
    ->where('t.serviceTypeName = :name')
    ->getQuery()
    ->execute(['name' => $name]);
  

由于您在此处对连接结果应用条件,因此使用LEFT JOIN或简单地JOIN是相同的。

参考文献:

How to Work with Doctrine Associations / Relations

how to do left join in doctrine

Left join ON condition AND other condition syntax in Doctrine