我需要将相同的列映射到2个不同的表(让我们说正常和扩展)。
/**
* @var ItemValue
*
* @OneToOne(targetEntity="ItemValue")
* @JoinColumn(name="id_value", referencedColumnName="id_value")
*/
private $value;
/**
* @var ItemValueExtended
*
* @OneToOne(targetEntity="ItemValueExtended")
* @JoinColumn(name="id_value", referencedColumnName="id_value")
*/
private $valueExtended;
/**
* @var string $isExtended
*
* @Column(name="is_extended", type="string", nullable=false)
*/
private $isExtended = 'YES';
我对使用DQL连接基于isExtended属性的数据没有问题:
"SELECT id,idv FROM ItemData id
JOIN id.value idv WHERE id.isExtended='NO'";
和
"SELECT id,idv FROM ItemData id
JOIN id.valueExtended idv WHERE id.isExtended='YES'";
但是当我想持久化一个新对象时,在id_value列中插入NULL ?!!
$oValue = ItemValue();
.
.
$oData = new ItemData();
$oData->setValue($oValue);
.
.
.
$em->persist($oData);
$em->flush();
来自Doctrine2文档:
在双向关联的情况下,必须更新
一个可能的解决方案是:
$oData = new ItemData();
$oData->setValue($oValue);
$oValue->setData($oData);
但是很乏味。另一个更好的是在一对一关联的两边设置级联选项:
@OneToOne(targetEntity="ItemValue"), cascade={"persist", "remove"})
这样你的代码就可以工作了。您可以在这里选择合适的级联选项。
在父实体和子实体都是新实体(都没有持久化)的情况下,父实体上的PrePersist生命周期事件可以提供帮助:
/**
* ....
*
* @ORM'HasLifecycleCallbacks
*/
class ParentEntity {...
/**
* @ORM'PrePersist()
*/
public function prePersist() {
foreach($this->getChildEntities() as $childEntity) {
$childEntity->setParent($this);
}
}
class ChildEntity {
....
这将在保存父节点时自动创建child -> parent关系。在许多情况下,Doctrine将能够在SQL级别解决其余的问题。