manymany导致重复输入错误


manyToMany causes duplicate entry error

我有一个User实体。这些用户可以成为朋友。所以我定义了一个自我引用的manymany单向关联(因为总是有互惠是友谊,对吧?)

YML中我的用户实体的一部分

manyToMany:
    friendList:
    targetEntity: User
    joinTable:
      name: user_friend
      joinColumns:
        user_id:
          referencedColumnName: id
      inverseJoinColumns:
        friend_id:
          referencedColumnName: id
    cascade: [persist]

当我调用$user->addFriendList($friend)时,在持久化和刷新之后,我有PDOException:

SQLSTATE[23000]: Integrity constraint violation: 1062

当我检查日志时,我可以看到doctrine试图执行相同的插入查询两次。

我的addFriendList函数

public function addFriendList(User $friend)
{
    if (!$this->friendList->contains($friend)) {
        $this->friendList[] = $friend;
        $friend->addFriendList($this);
    }
}

我哪里错了

我终于找到了解决问题的办法。然而,我仍然不知道这是一个Doctrine2的缺陷,或者它是否按照设计工作。

我需要在添加好友之前持久化我的用户和刷新。

所以我的工作代码是:
$em->persist($user);
$em-flush();
$user->addFriendList($friend);
$em->persist($user);
$em->flush();

@Reuven,你写道:

$this->friendList[] = $friend;
$friend->addFriendList($this);

好吧,你插入了两次关系。

这应该足够了:

$this->friendList[] = $friend;

这是因为您没有指定mappedBy(拥有方)和inversedBy。

查看用户和角色之间的多对多关系:

/**
 * @ORM'Entity
 * @ORM'Table(name="user")
 */
class User
{
    /**
     * @ORM'ManyToMany(targetEntity="Role", mappedBy="users")
     * @ORM'JoinTable(name="user_role",
     *      joinColumns={@ORM'JoinColumn(name="user_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM'JoinColumn(name="role_id", referencedColumnName="id")}
     * )
     */
    protected $roles;
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->roles = new ArrayCollection();
    }
    /**
     * Has role
     *
     * @param Role $role
     * @return bool
     */
    public function hasRole(Role $role)
    {
        return $this->roles->contains($role);
    }
    /**
     * Add role
     *
     * @param Role $role
     */
    public function addRole(Role $role)
    {
        if (!$this->hasRole($role)) {
            $this->roles->add($role);
            $role->addUser($this);
        }
    }
    /**
     * Remove roles
     *
     * @param Role $role
     */
    public function removeRole(Role $role)
    {
        if ($this->hasRole($role)) {
            $this->roles->removeElement($role);
            $role->removeUser($this);
        }
    }
}

.

/**
 * @ORM'Entity
 * @ORM'Table(name="role")
 */
class Role implements RoleInterface
{
    /**
     * @ORM'ManyToMany(targetEntity="User", inversedBy="roles")
     * @ORM'JoinTable(name="user_role",
     *      joinColumns={@ORM'JoinColumn(name="role_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM'JoinColumn(name="user_id", referencedColumnName="id")}
     * )
     */
    private $users;
    public function __construct()
    {
        $this->users = new ArrayCollection();
    }
    /**
     * Has user
     *
     * @param User $user
     * @return bool
     */
    public function hasUser(User $user)
    {
        return $this->users->contains($user);
    }
    /**
     * Add user
     *
     * @param User $user
     */
    public function addUser(User $user)
    {
        if (!$this->hasUser($user)) {
            $this->users->add($user);
            $user->addRole($this);
        }
    }
    /**
     * Remove user
     *
     * @param User $user
     */
    public function removeUser(User $user)
    {
        if ($this->hasUser($user)) {
            $this->users->removeElement($user);
            $user->addRole($this);
        }
    }
    /**
     * Get users
     *
     * @return ArrayCollection
     */
    public function getUsers()
    {
        return $this->users;
    }