Doctrine 要求在 OneToMany 单向关联中使用 mappedBy
Doctrine requires mappedBy in a OneToMany unidirectional association
当我尝试在这两个实体之间建立 OneToMany 单向关联时,我在尝试更新数据库架构时遇到此错误:
$ app/console doctrine:schema:update --dump-sql
[Doctrine\ORM\Mapping\MappingException]
OneToMany mapping on field 'address' requires the 'mappedBy'
attribute.
/**
* 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"?
提前致谢。
更新: 正如@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;
A OneToMany
必须是双向的,并且始终是关系的反面,如果您定义反面,则需要使用 [=14= 指向关系的拥有方] 属性。拥有方是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();
并且您跳过向数据库添加额外的连接 table。
如果您希望关系是单向的,您可以像更新中那样做;使用联接 table 定义 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)}
* )
*/
此解决方案的缺点是您无法从 Address
资源中找出哪个 User
拥有地址(Address
不知道 User
).这样的例子也可以在here in the Doctrine documentation chapter 5.6. One-To-Many, Unidirectional with Join Table.
中找到
当我尝试在这两个实体之间建立 OneToMany 单向关联时,我在尝试更新数据库架构时遇到此错误:
$ app/console doctrine:schema:update --dump-sql
[Doctrine\ORM\Mapping\MappingException]
OneToMany mapping on field 'address' requires the 'mappedBy' attribute.
/**
* 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"? 提前致谢。
更新: 正如@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;
A OneToMany
必须是双向的,并且始终是关系的反面,如果您定义反面,则需要使用 [=14= 指向关系的拥有方] 属性。拥有方是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();
并且您跳过向数据库添加额外的连接 table。
如果您希望关系是单向的,您可以像更新中那样做;使用联接 table 定义 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)}
* )
*/
此解决方案的缺点是您无法从 Address
资源中找出哪个 User
拥有地址(Address
不知道 User
).这样的例子也可以在here in the Doctrine documentation chapter 5.6. One-To-Many, Unidirectional with Join Table.