Doctrine orm 条令级联到具有单一关系的子对象

Doctrine orm 条令级联到具有单一关系的子对象,doctrine-orm,one-to-many,cascade,Doctrine Orm,One To Many,Cascade,我在使用拥有的子对象持久化和对象时遇到了一些问题。更具体地说,我有一个至少拥有一个PGPKey对象的用户类。 以下代码段失败: $user=新用户(“用户名”、“密码”); $em->persist($user); 错误如下: SQLSTATE[23000]:完整性约束冲突:1048列“PGPKeys.owner”不能为null 我的问题如下: 与PGPKey.owner相对应的User.idUser字段是一个GeneratedValue,因此在调用persist时仍然未定义。然后,条令尝试

我在使用拥有的子对象持久化和对象时遇到了一些问题。更具体地说,我有一个至少拥有一个PGPKey对象的用户类。

以下代码段失败:

$user=新用户(“用户名”、“密码”);
$em->persist($user);
错误如下:

SQLSTATE[23000]:完整性约束冲突:1048列“PGPKeys.owner”不能为null

我的问题如下: 与PGPKey.owner相对应的User.idUser字段是一个GeneratedValue,因此在调用persist时仍然未定义。然后,条令尝试首先保存PGPKey,但SQL不允许所有者为null。如果首先保存用户,则生成的id可用于保存到PGPkey的owner字段

我本以为条令在拥有对象之前就保存了拥有对象,但事实似乎并非如此,或者我遗漏了一些东西

永远不会执行User.postPersist()

User.php

/**
*@HasLifecycleCallbacks
*@实体
*/
类用户{
/**
*@Id
*@Column(type=“integer”,nullable=false,columnDefinition=“int(11)unsigned NOT NULL AUTO_INCREMENT”);
*@GeneratedValue(strategy=“AUTO”)
*/
受保护的$idUser;
/**
*@Column(type=“string”,nullable=false,columnDefinition=“VARCHAR(255)NOT NULL”)
*/
受保护的$username;
/**
*@OneToMany(targetEntity=“PGPKey”,mappedBy=“owner”,cascade={“persist”,“remove”},orphanremove=true)
*@var PGPKey[]
*/
受保护的$PGPKeys;
公共函数构造($username,$password)
{
$this->PGPKeys=new ArrayCollection();
$this->username=$username;
$this->setPassword($password);
}
/**@PostPersist*/
公共函数postPersist(){
foreach($this->PGPKeys as$key)
{
$key->setOwner($this->getId());
}
}
公共函数setPassword($newPassword,$oldPassword=false)
{
如果($oldPassword==false | |!计数($this->PGPKeys))
{
$newkey=new PGPKey($newPassword);
$newkey->setOwner($this->idUser);
$this->PGPKeys[]=$newkey;
}
其他的
{
$this->PGPKeys[count($this->PGPKeys)-1]->changePassword($oldPassword,$newPassword);
}
}
}
PGPKey.php

/**
*@实体
*/
类PGPKey
{
/**
*@Id
*@Column(type=“integer”,unique=true,columnDefinition=“int(11)无符号非空自动增量”);
*@GeneratedValue(strategy=“AUTO”)
*/
受保护的$idKey;
/**
*@Column(type=“integer”,columnDefinition=“int(11)unsigned NOT NULL”);
*@ManyToOne(targetEntity=“User”,inversedBy=“PGPKeys”);
*/
受保护的所有者;
公共函数构造($password)
{
//做RSA的事情
}
公共函数setOwner($ownerid)
{
$this->owner=$ownerid;
退还$this;
}
}

在与doctrine IRC上的某人聊天后,我终于可以提出一个解决方案:

在PGPKey类中,而不是

/**
*@Column(type=“integer”,columnDefinition=“int(11)unsigned NOT NULL”);
*@ManyToOne(targetEntity=“User”,inversedBy=“PGPKeys”);
*/
受保护的所有者;
公共函数setOwner($ownerid)
{
$this->owner=$ownerid;
退还$this;
}
应该是

/**
*@var用户
*@ManyToOne(targetEntity=“User”,inversedBy=“PGPKeys”);
*@JoinColumn(name=“owner”,referencedColumnName=“idUser”)
*/
受保护的所有者;
公共函数setOwner(用户$owner)
{
$this->owner=$owner;
退还$this;
}
因此,属性必须定义为JoinColumn,您必须引用整个所有者对象,而不仅仅是id。然后,Doctrine将使用JoinColumn注释中的信息从用户提取id。这样,用户首先被存储到数据库中,给定一个自动id,并且在执行时将该id传递给PGPKey子对象

$user=新用户(“用户名”、“密码”);
$em->persist($user)

希望这对其他人也有帮助。

在与doctrine IRC上的某人聊天后,我终于可以提出一个解决方案:

在PGPKey类中,而不是

/**
*@Column(type=“integer”,columnDefinition=“int(11)unsigned NOT NULL”);
*@ManyToOne(targetEntity=“User”,inversedBy=“PGPKeys”);
*/
受保护的所有者;
公共函数setOwner($ownerid)
{
$this->owner=$ownerid;
退还$this;
}
应该是

/**
*@var用户
*@ManyToOne(targetEntity=“User”,inversedBy=“PGPKeys”);
*@JoinColumn(name=“owner”,referencedColumnName=“idUser”)
*/
受保护的所有者;
公共函数setOwner(用户$owner)
{
$this->owner=$owner;
退还$this;
}
因此,属性必须定义为JoinColumn,您必须引用整个所有者对象,而不仅仅是id。然后,Doctrine将使用JoinColumn注释中的信息从用户提取id。这样,用户首先被存储到数据库中,给定一个自动id,并且在执行时将该id传递给PGPKey子对象

$user=新用户(“用户名”、“密码”);
$em->persist($user)
希望这对其他人也有帮助