DDC-2252: Trying to delete ManyToMany relatrionship with composite keys. #2952

Closed
doctrinebot opened this Issue Jan 22, 2013 · 13 comments

1 participant

@doctrinebot

Jira issue originally created by user yokoloko:

Hi,

When i try to delete some entities attached to an entity I've got the following message.

My entity is specified as follow.

    /****
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Entity\User\Account", inversedBy="memberships")
     * @ORM\JoinColumn(name="uid", referencedColumnName="uid")
     */
    protected $userAccount;

    /****
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Entity\Merchant\Account")
     * @ORM\JoinColumn(name="mch_accountid", referencedColumnName="accountid")
     */
    protected $merchantAccount;

    /****
     * @ORM\Column(type="datetime", name="date")
     * @var datetime
     */
    protected $date;

    /****
     * @ORM\Column(type="boolean")
     * @var boolean
     */
    protected $administrator;

    /****
     * @ORM\ManyToMany(targetEntity="Entity\User\Privilege", indexBy="privilegeid")
     * @ORM\JoinTable(name="fsbackend.user*mch_account*privilege",
     *   joinColumns={
     *       @ORM\JoinColumn(name="mch*accountid", referencedColumnName="mch*accountid"),
     *       @ORM\JoinColumn(name="uid", referencedColumnName="uid")
     *   },
     *   inverseJoinColumns={
     *       @ORM\JoinColumn(name="privilegeid", referencedColumnName="privilegeid")
     *   }
     * )
     */
    protected $privileges;

I delete the related entities

    $membership->getPrivileges()->clear();

    $this->_em->persist($userAccount);
    $this->_em->flush();

I tried on doctrine 2.1.7 and the last doctrine version and same thing happens.

Please find attached the error log.

@doctrinebot

Comment created by @ocramius:

[~yokoloko] is the schema validated by the cli tools?

@doctrinebot

Comment created by yokoloko:

Yes it's validated by the cli tools, if you are talking about the orm:validate-schema command.

@doctrinebot

Comment created by yokoloko:

I think the problem is that my @Id are entities.

@doctrinebot

Comment created by @ocramius:

[~yokoloko] can you abstract it away into a test?

@doctrinebot

Comment created by yokoloko:

Here is my test case.

I put it IN Doctrine\Test\ORMJT.
I don't really know if you need something else, please let met know.

<?php

namespace Doctrine\Tests\ORMJT;

use Doctrine\ORM\Query;
use Doctrine\Common\Collections\ArrayCollection;

require*once __DIR_* . '/../TestInit.php';

/****
 * Functional tests for the Single Table Inheritance mapping strategy.
 *
 * @author robo
 */
class AdvancedAssociationTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
    protected function setUp() {
        parent::setUp();
        try {
            $this->_schemaTool->createSchema(array(
                $this->_em->getClassMetadata('Doctrine\Tests\ORMJT\User'),
                $this->_em->getClassMetadata('Doctrine\Tests\ORMJT\MerchantAccount'),
                $this->_em->getClassMetadata('Doctrine\Tests\ORMJT\Membership'),
                $this->_em->getClassMetadata('Doctrine\Tests\ORMJT\Privilege')
            ));
        } catch (\Exception $e) {
            // Swallow all exceptions. We do not test the schema tool here.
        }
    }

    public function testIssue()
    {
        $user = new User;
        $merchantAccount = new MerchantAccount;
        $privilege = new Privilege;
        $membership = new Membership($user, $merchantAccount);
        $membership->addPrivilege($privilege);

        $this->_em->persist($user);
        $this->_em->persist($merchantAccount);
        $this->_em->persist($privilege);
        $this->_em->flush();

        $this->_em->persist($membership);
        $this->_em->flush();

        $membership->getPrivileges()->clear();

        $this->_em->flush();

        // Never reached
        $this->assertTrue(true);
    }
}


/****
 * @Entity
 * @Table(name="mch_account")
 */
class MerchantAccount
{
    /****
     * @Id @GeneratedValue
     * @Column(type="bigint")
     * @var bigint $accountid
     */
    protected $accountid;
}

/****
 * @Entity(repositoryClass="Repository\User\PrivilegeRepository")
 * @Table(name="acl_privilege")
 */
class Privilege
{
    /****
     * @Id @GeneratedValue
     * @Column(type="bigint")
     * @var integer
     */
    protected $privilegeid;
}

/****
 * @Entity
 * @Table(name="user_account")
 */
class User {
    /****
     * @Id @GeneratedValue
     * @Column(type="bigint")
     * @var integer
     */
    protected $uid;

    /****
     * @OneToMany(targetEntity="Membership", mappedBy="userAccount", cascade={"persist"})
     * @JoinColumn(name="uid", referencedColumnName="uid")
     */
    protected $memberships;

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

    public function getMemberships()
    {
        return $this->memberships;
    }

    public function addMembership(Membership $membership)
    {
        $this->memberships[] = $membership;
    }
}

/****
 * @Entity
 * @Table(name="mch*account*member")
 * @HasLifecycleCallbacks
 */
class Membership
{
    /****
     * @Id
     * @ManyToOne(targetEntity="User", inversedBy="memberships")
     * @JoinColumn(name="uid", referencedColumnName="uid")
     */
    protected $userAccount;

    /****
     * @Id
     * @ManyToOne(targetEntity="MerchantAccount")
     * @JoinColumn(name="mch_accountid", referencedColumnName="accountid")
     */
    protected $merchantAccount;

    /****
     * @ManyToMany(targetEntity="Privilege", indexBy="privilegeid")
     * @JoinTable(name="user*mch_account*privilege",
     *   joinColumns={
     *       @JoinColumn(name="mch*accountid", referencedColumnName="mch*accountid"),
     *       @JoinColumn(name="uid", referencedColumnName="uid")
     *   },
     *   inverseJoinColumns={
     *       @JoinColumn(name="privilegeid", referencedColumnName="privilegeid")
     *   }
     * )
     */
    protected $privileges;

    public function **construct(User $user, MerchantAccount $merchantAccount)
    {
        $this->userAccount = $user;
        $this->merchantAccount = $merchantAccount;
        $this->privileges = new ArrayCollection();
    }

    public function addPrivilege($privilege)
    {
        $this->privileges[] = $privilege;
    }

    public function getPrivileges()
    {
        return $this->privileges;
    }
}

And i've got the following error

1) Doctrine\Tests\ORMJT\AdvancedAssociationTest::testIssue
Exception: [PHPUnit*Framework_Error_Notice] Undefined index: mch*accountid
@doctrinebot

Comment created by @ocramius:

Thank you so far, this makes it much easier to work with it!

@doctrinebot

Comment created by yokoloko:

Interesting fact, if I only have one column in my jointable it works fine.

eg.

class Membership
     *   ....
     *   @JoinTable(name="user*mch_account*privilege",
     *       joinColumns={
     *           @JoinColumn(name="uid", referencedColumnName="uid")
     *       }
     *   ....
@doctrinebot

Comment created by yokoloko:

Ok here is my two cents solution. passes the tests.

@doctrinebot

Comment created by yokoloko:

Hi, any update on this issue?

@doctrinebot

Comment created by @ocramius:

[~yokoloko] will be checking this tomorrow

@doctrinebot

Comment created by yokoloko:

Everything ok with the check?

@doctrinebot

Comment created by @FabioBatSilva:

Fixed by : cef2089

@doctrinebot

Issue was closed with resolution "Fixed"

@doctrinebot doctrinebot added this to the 2.4 milestone Dec 6, 2015
@doctrinebot doctrinebot closed this Dec 6, 2015
@doctrinebot doctrinebot added the Bug label Dec 7, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment