1

我试图弄清楚如何在preUpdate方法中回滚已更改实体的状态(如果有区别,我将使用注释方法)。

我尝试使用EntityManager::refresh($entity)and 虽然它似乎确实恢复了实体,但它仍然继续并将更改保存到数据库中。

我读过我需要通过调用重新计算更改集,$em->getUnitOfWork()->computeChangeSet($em->getClassMetaData(get_class($this)), $this);但这并不能解决问题。

反正有没有让UnitOfWork忽略更改/重新计算正确?

<?php 
class Status extends Entity {

    /**
     * @PreUpdate
     */
    public function preUpdate() {
        if (!$this->canSave()) {
            $this->reset();
        }
    }

    public function reset() {
        $em = self::getEntityManager();
        $em->refresh($this);
        $em->getUnitOfWork()
           ->computeChangeSet($em->getClassMetaData(get_class($this)), $this);
    }

    public function canSave() { return false; }
?>

<?php
// Bootstrap for testing/debugging
include 'common.php';

$log = \Zend_Registry::get('log');

$x = Status::find(31); // Retrieve entity from DB
$log->debug("Original: " . $x->getDateLastSeen() . "\n");

$x->setDateLastSeen(new \DateTime());
$log->debug("Set to: " . $x->getDateLastSeen() . "\n");

$x->save();
$log->debug("Saved to: " . $x->getDateLastSeen() . "\n");

输出:

2013-02-14T23:13:22+00:00 DEBUG (7): Original: 2013-02-14 23:08:22
2013-02-14T23:13:22+00:00 DEBUG (7): Set to: 2013-02-14 23:13:22
2013-02-14T23:13:22+00:00 DEBUG (7): Saved to: 2013-02-14 23:08:22

一切看起来都很好,但是当我查看我的数据库日志时,我看到:

409705 Query    UPDATE devices_statuses SET date_last_seen = '2013-02-14 23:13:22' WHERE id = 31
409705 Query    commit
4

1 回答 1

2

这已经由 ORM 本身处理(参见https://github.com/doctrine/doctrine2/blob/2.3.2/lib/Doctrine/ORM/UnitOfWork.php#L970-L974

这里的问题是DateTime分配给的实例date_last_seen(或更好的映射到它的字段)具有不同的对象哈希(用 进行检查spl_object_hash())。

对于 ORM,这是一个变更集。要有效地重置您的实例,您需要手动调用Doctrine\ORM\UnitOfWork#clearEntityChangeSet(spl_object_hash($this)).

此外,考虑将此代码从实体移出到专用的事件侦听器中:您的实体不应该EntityManager以任何方式了解持久层或关于持久层。

于 2013-02-15T08:56:51.447 回答