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

时间:2015-10-13 16:50:51

标签: symfony doctrine-orm doctrine

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

  

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

     

[学说\ ORM \映射\ MappingException]
  字段'地址'上的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;

    // ...
}

如果关联是单向的,为什么需要“mappedBy”? 提前谢谢。

UPDATE:正如@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;

1 个答案:

答案 0 :(得分:10)

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

User中,您的关联具有mappedBy="user"属性,并指向拥有方Address

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

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;

此解决方案的优点是您可以通过执行以下操作找到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)}
 * )
 */

此解决方案的缺点是,您无法找到User资源中Address拥有该Address资源的地址User不知道Process p = Runtime.getRuntime().exec(System.getenv("windir") +"\\system32\\"+"tasklist.exe"); try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) { while ((line = input.readLine()) != null) { System.out.println(line); //<-- Parse data here. } } )。这样的例子也可以找到here in the Doctrine documentation chapter 5.6. One-To-Many, Unidirectional with Join Table