【问题标题】:Symfony2: Left Join producing wrong querySymfony2:左连接产生错误的查询
【发布时间】:2015-01-16 01:12:52
【问题描述】:

我正在尝试使用这样的学说查询构建器构建查询:

$q = $this
        ->createQueryBuilder('u')
        ->select('u, r')
        ->leftJoin('u.roles', 'r')
        ->where('u.username = :username OR u.email = :email')
        ->setParameter('username', $username)
        ->setParameter('email', $username)
        ->getQuery();`

此代码产生 2 个查询:

查询 1 正确

SELECT t0.user_id AS user_id1, t0.username AS username2, t0.salt AS salt3, t0.password AS password4, t0.email AS email5, t0.is_active AS is_active6, t0.created AS created7, t0.updated AS updated8, t0.last_login AS last_login9 
FROM users t0 
WHERE t0.username = ? 
LIMIT 1 

查询 2 不正确:

SELECT t0.role_id AS role_id1, t0.role AS role2 
FROM roles t0 
INNER JOIN user_role ON t0.id = user_role.role_id 
WHERE user_role.user_fk = ?

查询 2 应该是:

SELECT t0.role_id AS role_id1, t0.role AS role2 
FROM roles t0 
INNER JOIN user_role ON t0.role_id = user_role.role_fk 
WHERE user_role.user_fk = ?

实体\角色如下所示:

/**
 * @ORM\Table(name="roles")
 * @ORM\Entity(repositoryClass="XXX\XXXBundle\Entity\Repository\RoleRepository")
 */
class Role implements RoleInterface
{
    /**
     * @ORM\Id
     * @ORM\Column(name="role_id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $_roleId;
    /**
     * @ORM\Column(name="role", type="string", length=20, unique=true)
     */
    protected $_role;
    /**
     * @ORM\ManyToMany(targetEntity="User", mappedBy="roles")
     * @ORM\JoinTable(name="user_role",
     *     joinColumns={@ORM\JoinColumn(name="role_fk", referencedColumnName="role_id")})
     */
    private $_users;
...

Entity\User 看起来像这样:

class User implements UserInterface, \Serializable  
    {
        /**
         * @ORM\Column(name="user_id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $_userId;
        ...
        /**
         * @ORM\ManyToMany(targetEntity="Role", inversedBy="users")
         * @ORM\JoinTable(name="user_role",
         *     joinColumns={@ORM\JoinColumn(name="user_fk", referencedColumnName="user_id")})
         */
        protected $_roles;
    ...

Entity\Role 代码中的注释说明了要使用的列名,并且语句的 SELECT 部分使用了正确的名称。语句的 WHERE 部分使用了正确的列 user_role.user_fk,这在 Entity\User 代码中定义。

如何停止使用不存在的列名并为语句的 INNER JOIN 部分使用定义的列名?

【问题讨论】:

  • 我很难理解这个问题。由于 where 条件错误,这两个 sql 语句都不应该由您发布的查询产生。为什么你关心“神奇的列名”?你得到了意想不到的东西吗?
  • 语句的 WHERE 部分是正确的,user_role.user_fk 是正确的列名,因为它是来自用户表的连接列。问题是 doctrtine 正在生成 sql 语句的 INNER JOIN 部分并使用不存在的列名。角色表中不存在id列,如Entity\Role代码所示,user_role表中不存在role_id列。 user_role 表中的 join 列是 role_fk,如 Entity\Role 代码所示。
  • 如果你这么说。您的查询有“where('u.username = :username OR u.email = :email')”,我在您发布的 sql 中没有看到它。有些情况下,人们一直在编辑一个文件但运行另一个文件。?第一次查询/第二次查询的整个概念似乎很奇怪。一般来说,一个查询总是生成相同的 sql。

标签: php mysql symfony doctrine-orm


【解决方案1】:

我找到了一个可行的解决方案。

Entity\User 需要修改以在注释中包含 inverseJoinColumns,如下所示:

/**
 * @ORM\ManyToMany(targetEntity="Role", inversedBy="_users")
 * @ORM\JoinTable(name="user_role",
 *     joinColumns={@ORM\JoinColumn(name="user_fk", referencedColumnName="user_id")},
 *     inverseJoinColumns={@ORM\JoinColumn(name="role_fk", referencedColumnName="role_id")})
 */
protected $_roles;

Entity\Role 需要更改以包含 inverseJoinColumns,如下所示:

/**
 * @ORM\ManyToMany(targetEntity="User", mappedBy="_roles")
 * @ORM\JoinTable(name="user_role",
 *     joinColumns={@ORM\JoinColumn(name="role_fk", referencedColumnName="role_id")},
 *     inverseJoinColumns={@ORM\JoinColumn(name="user_fk", referencedColumnName="user_id")})
 */
private $_users;

并且 createQueryBuilder 代码需要如下所示:

$q = $this
        ->createQueryBuilder('u')
        ->select('u, r')
        ->from('XXXXXXBundle:User', 'u')
        ->leftJoin('u.roles', 'r', \Doctrine\ORM\Query\Expr\Join::ON, 'user_role.role_kf = r.role_id')
        ->where('u.username = :username OR u.email = :email')
        ->setParameter('username', $username)
        ->setParameter('email', $username)
        ->getQuery();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-13
    相关资源
    最近更新 更多