DDC-992: ManyToMany self referencing association bug with lazy loading #1237

Closed
opened 2026-01-22 13:06:53 +01:00 by admin · 5 comments
Owner

Originally created by @doctrinebot on GitHub (Jan 19, 2011).

Originally assigned to: @beberlei on GitHub.

Jira issue originally created by user vigor_bg:

Hi there I encountered a bug. When was trying to get ManyToMany self referencing association via lazy loading.

Here is my Entity.

use Doctrine\Common\Collections\ArrayCollection;

/****
 *
 * @Table(name="Roles")
 * @entity(repositoryClass="Users*Model*RoleRepo")
 */

class Users*Model_Entity_Role extends Viscomp_Doctrine_Entity*Abstract
{
/****
     *  @Id  @Column(name="roleID", type="integer")
     *  @GeneratedValue(strategy="AUTO")
     *
     */
    protected $roleID;

    /****
     * @Column (name="name", type="string", length="45")
     *
     *
     */
    protected $name;

    /****
     * @Column (name="shortName", type="string", length="45")
     *
     *
     */
    protected $shortName;

    /****
     * @ManyToMany (targetEntity="Users*Model_Entity*Role", mappedBy="extends")
     */
    protected $extendedBy;

    /****
     * @ManyToMany (targetEntity="Users*Model_Entity*Role", inversedBy="extendedBy")
     * @JoinTable (name="RoleRelations",
     *      joinColumns={@JoinColumn(name="roleID", referencedColumnName="roleID")},
     *      inverseJoinColumns={@JoinColumn(name="extendsRoleID", referencedColumnName="roleID")}
     *      )
     */
    protected $extends;

    public function **construct() {
        $this->extends = new ArrayCollection;
        $this->extendedBy = new ArrayCollection;
   }

}

When I call

$test = $this->getEntityManager()->getRepository('Users*Model_Entity*Role')->findOneBy(array('roleID' => 3));
Doctrine\Common\Util\Debug::dump($test); die;

The SQL that is generated is :


SELECT t0.roleID AS roleID1, t0.name AS name2, t0.shortName AS shortName3 FROM Roles t0 WHERE t0.roleID = ? array(1) { [0]=>  int(3) } 

SELECT t0.roleID AS roleID1, t0.name AS name2, t0.shortName AS shortName3 FROM Roles t0 INNER JOIN RoleRelations ON t0.roleID = RoleRelations.roleID WHERE RoleRelations.extendsRoleID = ?
array(1) {
  [0]=>
  int(3)
}
SELECT t0.roleID AS roleID1, t0.name AS name2, t0.shortName AS shortName3 FROM Roles t0 INNER JOIN RoleRelations ON t0.roleID = RoleRelations.extendsRoleID WHERE t0.roleID = ?
array(1) {
  [0]=>
  int(3)
}

In the last SQL query there is a mistake in the where clause it should be RoleRelations.roleID = ? and not t0.roleID = ?. And because of that it is not returning correct result.

Originally created by @doctrinebot on GitHub (Jan 19, 2011). Originally assigned to: @beberlei on GitHub. Jira issue originally created by user vigor_bg: Hi there I encountered a bug. When was trying to get ManyToMany self referencing association via lazy loading. Here is my Entity. ``` use Doctrine\Common\Collections\ArrayCollection; /**** * * @Table(name="Roles") * @entity(repositoryClass="Users*Model*RoleRepo") */ class Users*Model_Entity_Role extends Viscomp_Doctrine_Entity*Abstract { /**** * @Id @Column(name="roleID", type="integer") * @GeneratedValue(strategy="AUTO") * */ protected $roleID; /**** * @Column (name="name", type="string", length="45") * * */ protected $name; /**** * @Column (name="shortName", type="string", length="45") * * */ protected $shortName; /**** * @ManyToMany (targetEntity="Users*Model_Entity*Role", mappedBy="extends") */ protected $extendedBy; /**** * @ManyToMany (targetEntity="Users*Model_Entity*Role", inversedBy="extendedBy") * @JoinTable (name="RoleRelations", * joinColumns={@JoinColumn(name="roleID", referencedColumnName="roleID")}, * inverseJoinColumns={@JoinColumn(name="extendsRoleID", referencedColumnName="roleID")} * ) */ protected $extends; public function **construct() { $this->extends = new ArrayCollection; $this->extendedBy = new ArrayCollection; } } ``` When I call ``` $test = $this->getEntityManager()->getRepository('Users*Model_Entity*Role')->findOneBy(array('roleID' => 3)); Doctrine\Common\Util\Debug::dump($test); die; ``` The SQL that is generated is : ``` SELECT t0.roleID AS roleID1, t0.name AS name2, t0.shortName AS shortName3 FROM Roles t0 WHERE t0.roleID = ? array(1) { [0]=> int(3) } SELECT t0.roleID AS roleID1, t0.name AS name2, t0.shortName AS shortName3 FROM Roles t0 INNER JOIN RoleRelations ON t0.roleID = RoleRelations.roleID WHERE RoleRelations.extendsRoleID = ? array(1) { [0]=> int(3) } SELECT t0.roleID AS roleID1, t0.name AS name2, t0.shortName AS shortName3 FROM Roles t0 INNER JOIN RoleRelations ON t0.roleID = RoleRelations.extendsRoleID WHERE t0.roleID = ? array(1) { [0]=> int(3) } ``` In the last SQL query there is a mistake in the where clause it should be RoleRelations.roleID = ? and not t0.roleID = ?. And because of that it is not returning correct result.
admin added the Bug label 2026-01-22 13:06:53 +01:00
admin closed this issue 2026-01-22 13:06:54 +01:00
Author
Owner

@doctrinebot commented on GitHub (Jan 19, 2011):

Comment created by vigor_bg:

The solution that I found is in the class BasicEntityPersister on line 1123 we have

 $conditionSql .= $this->*getSQLTableAlias($this->*class->name) . '.';

and i replace it with

if ($assoc !== null
    && $assoc['targetEntity'] == $assoc['sourceEntity']
    && $assoc['type'] == ClassMetadata::MANY*TO*MANY) {
        $owningAssoc = $assoc['isOwningSide'] ? $assoc : $this->_em->getClassMetadata($assoc['targetEntity'])
                                                                   ->associationMappings[$assoc['mappedBy']];
    $conditionSql .= $this->*class->getQuotedJoinTableName($owningAssoc, $this->*platform) . '.';

} else {
         $conditionSql .= $this->*getSQLTableAlias($this->*class->name) . '.';
}

I am not sure if that is the correct answer but as far as i have tested it doesn't mess up with the normal many to many association via join table.

@doctrinebot commented on GitHub (Jan 19, 2011): Comment created by vigor_bg: The solution that I found is in the class BasicEntityPersister on line 1123 we have ``` $conditionSql .= $this->*getSQLTableAlias($this->*class->name) . '.'; ``` and i replace it with ``` if ($assoc !== null && $assoc['targetEntity'] == $assoc['sourceEntity'] && $assoc['type'] == ClassMetadata::MANY*TO*MANY) { $owningAssoc = $assoc['isOwningSide'] ? $assoc : $this->_em->getClassMetadata($assoc['targetEntity']) ->associationMappings[$assoc['mappedBy']]; $conditionSql .= $this->*class->getQuotedJoinTableName($owningAssoc, $this->*platform) . '.'; } else { $conditionSql .= $this->*getSQLTableAlias($this->*class->name) . '.'; } ``` I am not sure if that is the correct answer but as far as i have tested it doesn't mess up with the normal many to many association via join table.
Author
Owner

@doctrinebot commented on GitHub (Jan 23, 2011):

Comment created by @beberlei:

There is a simple workaround if you rename the "roleID" from the join table to something else, childRoleID for example. This should work for now. I am looking into a way to fix this issue.

@doctrinebot commented on GitHub (Jan 23, 2011): Comment created by @beberlei: There is a simple workaround if you rename the "roleID" from the join table to something else, childRoleID for example. This should work for now. I am looking into a way to fix this issue.
Author
Owner

@doctrinebot commented on GitHub (Jan 23, 2011):

Comment created by vigor_bg:

Ok thanks :)

@doctrinebot commented on GitHub (Jan 23, 2011): Comment created by vigor_bg: Ok thanks :)
Author
Owner

@doctrinebot commented on GitHub (Mar 20, 2011):

Comment created by @beberlei:

Fixed, merged into 2.0.x branch.

@doctrinebot commented on GitHub (Mar 20, 2011): Comment created by @beberlei: Fixed, merged into 2.0.x branch.
Author
Owner

@doctrinebot commented on GitHub (Mar 20, 2011):

Issue was closed with resolution "Fixed"

@doctrinebot commented on GitHub (Mar 20, 2011): Issue was closed with resolution "Fixed"
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#1237