Doctrine要求在OneToMany单向关联中使用mappedBy

mev*_*vqz 5 doctrine symfony doctrine-orm

当我尝试在这两个实体之间建立OneToMany单向关联时,我在尝试更新数据库模式时遇到此错误:

$ app/console doctrine:schema:update --dump-sql

[Doctrine\ORM\Mapping\MappingException]
字段'address'上的OneToMany映射需要'mappedBy'属性.

/**
 * User
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class User
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\OneToMany(targetEntity="Address")
     * @ORM\JoinTable(name="users_address",
     *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="address_id", referencedColumnName="id", unique=true)}
     *      )
     */
    private $address;

    //...
}

/**
 * Address
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class Address
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

如果关联是单向的,为什么需要"mappedBy"?提前致谢.

更新:正如@tchap在评论中所提到的,单向OneToMany可以与@ManyToMany映射,并在其中一个连接列上使用唯一约束来强制执行onetomany基数.正如文档所说,但对我来说有点混乱,因为已有@OneToMay注释.所以我只需要将上面的代码改为此(只需将@OneToMany更改为@ManyToMany):

/**
 * @ORM\ManyToMany(targetEntity="Address")
 * @ORM\JoinTable(name="users_address",
 *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="address_id", referencedColumnName="id", unique=true)}
 * )
 */
private $address;
Run Code Online (Sandbox Code Playgroud)

Wil*_*ilt 11

A OneToMany必须是双向的,并且始终是关系的反面,如果定义反面,则需要指向与mappedBy属性的关系的拥有方.拥有方是ManyToOne.在你的情况下,这将是这样的:

User您的关联中有一个mappedBy="user"属性并指向拥有方Address:

/** ONE-TO-MANY BIDIRECTIONAL, INVERSE SIDE
 * @var Collection
 * @ORM\OneToMany(targetEntity="Address", mappedBy="user")
 */
protected $addresses;
Run Code Online (Sandbox Code Playgroud)

Address您的关联中有一个inversedBy="addresses"属性并指向反面User:

/** MANY-TO-ONE BIDIRECTIONAL, OWNING SIDE
 * @var User
 * @ORM\ManyToOne(targetEntity="User", inversedBy="addresses")
 * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
 */
protected $user;
Run Code Online (Sandbox Code Playgroud)

此解决方案的优点是您可以找到Address通过执行操作的用户:$address->getUser();并且您跳过向数据库添加其他连接表.


如果您希望关系是单向的,您可以像在更新中那样做; 定义ManyToMany与连接表的关系,并在address_id列上添加唯一约束.

/**
 * @ORM\ManyToMany(targetEntity="Address")
 * @ORM\JoinTable(name="user_address",
 *     joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
 *     inverseJoinColumns={@ORM\JoinColumn(name="address_id", referencedColumnName="id", unique=true)}
 * )
 */
Run Code Online (Sandbox Code Playgroud)

此解决方案的缺点是您无法找到资源中的哪个User地址Address(Address不知道User).这样的例子也可以在Doctrine文档第5.6章中找到.具有连接表的一对多,单向.