让我们考虑以下情况。
我有这些实体
class RoomI18N
{
/**
* @ORM\Id
* @ORM\ManyToOne(targetEntity="TextType")
* @ORM\JoinColumn(name="text_type_id", referencedColumnName="id")
*/
protected $text_type;
/**
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Language")
* @ORM\JoinColumn(name="language_id", referencedColumnName="id")
*/
protected $language;
/**
* @ORM\id
* @ORM\ManyToOne(targetEntity="Room", inversedBy="room_i18n")
*/
protected $room;
[...]
}
和
class Room
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
[...]
/**
* @ORM\OneToMany(targetEntity="RoomI18N", mappedBy="room", cascade={"remove", "persist"})
*/
protected $room_i18n;
[...]
}
如您所见,RoomI18N
实体具有由其他表(实体)的三个主键组成的复合键。这是设计数据库时非常常见的方法,这也会节省“空间”,因为我不需要存储我不需要的额外字段(id)。此外,数据复制是最小的,RoomI18N
(复合)密钥不会存储在表的其他位置。
说,我遇到了麻烦,因为RoomI18N
是关系的拥有方,我为Room
实体创建了一个表单,我可以 - 或者不 - 插入一些文本信息国际化。
当我将请求绑定到我的表单并持久保存Room
对象时,我收到该错误(*故意放在那里)
app.ERROR:*****中的例外:****** \ Entity \ RoomI18N类型的实体 缺少字段'room'的已分配ID。标识符生成 此实体的策略要求之前填充ID字段 调用EntityManager#persist()。如果要自动生成 您需要调整元数据映射 因此。 [] []
我很清楚发生了什么:doctrine尝试持久化RoomI18N
对象 BEFORE 房间对象,因此,Room
对象仍然没有ID。
好的,如果出现以下情况,我该如何摆脱这种情况:
RoomI18N
主键RoomI18N
相关对象,保留它,将它们再次放入原始Room
对象并再次保存到DB 此外,当然,我已经尝试删除cascade
挂钩并手动持久化对象 - 只是为了尝试,我确信这不起作用 - 当然没有任何改变。
我控制器我将所有RoomI18N
设置如下
$handled_languages = $lodging->getHandledLanguages();
[...]
foreach ($handled_languages as $language) {
$room_text_i18n = new RoomI18N();
$room_text_i18n->setLanguage($language);
[...]
$room->addRoomI18n($room_text_i18n); //fetched before
}
答案 0 :(得分:0)
好的,我找到了解决办法
我需要显式将反转的对象(Room
)设置为拥有的一方(RoomI18N
)。
基本上我改变了控制器的代码如下
$handled_languages = $lodging->getHandledLanguages();
[...]
foreach ($handled_languages as $language) {
$room_text_i18n = new RoomI18N();
$room_text_i18n->setLanguage($language);
[...]
$room->addRoomI18n($room_text_i18n); //fetched before
$room_text_i18n->setRoom($room);
}
提示来自:enter link description here
正如Jasper所说,最好修改addRoomI18n()
函数(Room
实体,所以反面),如下所示
public function addRoomI18n(RoomI18N $roomI18n)
{
$this->room_i18n[] = $roomI18n;
$roomI18n->setRoom($this); //As is the owning side, I need to set it explicitly otherwise I need to set everytime
//I want to persist a Room object
return $this;
}
答案 1 :(得分:0)
您可以在主实体中添加外键实体时添加主键实体实例的实例。
public function addRoomI18n(RoomI18n $RoomI18n)
{
$this->RoomI18n[] = $RoomI18n;
$RoomI18n->setRoom($this);
return $this;
}