根据条令2.0文档(http://docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html)
。。预先存在的托管实体被持久化操作忽略。但是,如果从X到这些其他实体的关系是用cascade=persist或cascade=ALL映射的,则持久化操作级联到X引用的实体(请参阅"传递持久化")。">
我的理解是,级联到引用的托管实体应该会导致引用的实体被持久化操作忽略(情况3):
可达性持久性:级联持久
- 集合中标记为级联持久化的新实体将由条令直接持久化
- 集合中未标记为级联持久的新实体将产生异常并回滚flush()操作
- 跳过没有新实体的集合
然而,情况并非如此。我有一个托管Channel
实体,其中包含1:n个Properties
和Data
实体。创建Channel
实体时,会检索但不会修改某些属性。
当我添加数据并通过持久化实体时
$channel->addData(new ModelData($channel, $timestamp, $value));
$em->persist();
我可以看到用于编写新Data
实体的SQL,但也可以看到对现有Properties
的更新(使用旧的、未更改的值)。
为什么条令(2.4.1)坚持管理实体的关系
实体定义如下:
class Channel extends Entity {
/**
* @OneToMany(targetEntity="Data", mappedBy="channel", cascade={"persist"}, orphanRemoval=true)
* @OrderBy({"timestamp" = "ASC"})
*/
protected $data = NULL;
/**
* Constructor
*/
public function __construct($type) {
parent::__construct($type);
$this->data = new ArrayCollection();
}
/**
* Add a new data to the database
*/
public function addData(VolkszaehlerModelData $data) {
$this->data->add($data);
}
...
}
abstract class Entity {
/**
* @OneToMany(targetEntity="Property", mappedBy="entity", cascade={"remove", "persist"}, orphanRemoval=true)
* @OrderBy({"key" = "ASC"})
*/
protected $properties = NULL;
/**
* Constructor
*
* @param string $type
*/
public function __construct($type) {
if (!DefinitionEntityDefinition::exists($type)) {
throw new Exception('Unknown entity type: '' . $type . ''');
}
$this->properties = new CollectionsArrayCollection();
}
...
}
我终于发现,Doctrine不坚持持久化引用的托管实体。
然而,在上述情况下,我修改了相关实体(更改了一些属性的类型),由于在计算更改集时进行了===
比较,Doctrine确实将其解释为更新。
有一些关于使用PostFlush
事件来防止这种情况的讨论,但尚未得出结论:https://github.com/doctrine/doctrine2/pull/382#issuecomment-43421295