Php 为什么空事务会保留我的实体(原则)?

Php 为什么空事务会保留我的实体(原则)?,php,mysql,doctrine-orm,Php,Mysql,Doctrine Orm,我有一个被持久化到数据库的条令实体,而我从未调用persist或flush 我在下面简单地再现了这个问题。正如您将看到的,该脚本从名为MyEntity的数据库表中加载一行,并获得一个php对象,该行的字段作为属性。然后,脚本更改其中一个属性,但不调用persist或flush。然后,脚本创建一个空事务,它什么也不做。奇怪的是,这使得对象持久化,因为对php对象所做的更改也在数据库中进行。我没想到这个脚本会对数据库做任何更改 这里发生了什么 请注意,如果删除空事务,问题将消失,并且不会对数据库进行

我有一个被持久化到数据库的条令实体,而我从未调用persist或flush

我在下面简单地再现了这个问题。正如您将看到的,该脚本从名为MyEntity的数据库表中加载一行,并获得一个php对象,该行的字段作为属性。然后,脚本更改其中一个属性,但不调用persist或flush。然后,脚本创建一个空事务,它什么也不做。奇怪的是,这使得对象持久化,因为对php对象所做的更改也在数据库中进行。我没想到这个脚本会对数据库做任何更改

这里发生了什么

请注意,如果删除空事务,问题将消失,并且不会对数据库进行任何更改

下面是代码(test.php):

创建MyEntity条令实体(testEntities\MyEntity.php):


条令手册:9。事务和并发->(在底部):

连接#事务($func)和 EntityManager#transactional($func)是后一种抽象 在事务提交之前刷新EntityManager并关闭 发生异常时,EntityManager将正常运行(除了 回滚事务)


因此:
EntityManager#transactional($func)
在事务提交之前刷新EntityManager(如果
$func
调用成功-您的案例)。

它可能会刷新EntityManager,但如果我从未调用persist,它不应该将任何内容保存到数据库中,是吗?不,您错了。这取决于跟踪策略。阅读手册中的内容。默认策略是延迟隐式的。使用此策略,条令在提交时通过逐个属性的比较检测更改,还检测其他受管实体引用的实体或新实体的更改(“可访问性持久化”)。如果将
@ChangeTrackingPolicy(“DEFERRED\u EXPLICIT”)
注释添加到
类MyEntity
,你更高的评论变成事实,条令必须停止保存你的例子的更改。我明白了。在本例中,它现在起作用了。在我的实际代码中没有,所以问题一定在其他地方。一旦我成功地重现了这个问题,我将开始一个新的问题。非常感谢您的帮助。我将EntityManager#beginTransaction更改为Connection#beginTransaction,但没有帮助-尽管我没有对实体调用persist,但它们仍然保持不变。
<?php

    use Doctrine\ORM\Tools\Setup;

    require_once("Doctrine/ORM/Tools/Setup.php");
    Setup::registerAutoloadPEAR();

    $classloader = new Doctrine\Common\ClassLoader('testEntities', __DIR__);
    $classloader->register();

    $paths = array();
    $isDevMode = true;
    $config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
    $dbParams = array("driver" => "pdo_mysql",
        "host" => "localhost",
        "user" => "username",
        "password" => "password",
        "dbname" => "databaseName",
        "charset" => "utf8");

    $em = \Doctrine\ORM\EntityManager::create($dbParams, $config);
    $em->getConnection()->exec("SET NAMES UTF8");

    $matches = $em->getRepository('testEntities\\MyEntity')->findBy(array('ID' => 1));
    echo("<pre>");

    if (!empty($matches)) {
        $object = $matches[0];
        print_r($object);
        $object->Content = "WILL IT BLEND?";
        print_r($object);
    }
    $em->transactional(function($em) {
        // Nothing happens here, but if I comment out the call to transactional, the behaviour of the script changes.
    });

    echo("</pre>Done!");
?>
CREATE TABLE `MyEntity` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Content` varchar(500) COLLATE utf8_swedish_ci NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci;

INSERT INTO MyEntity (ID, Content) VALUES (NULL, "Hello World");
<?php

    namespace testEntities;

    /** @Entity @Table(name="MyEntity")*/
    class MyEntity
    {
        /**
         * @Id @GeneratedValue(strategy="AUTO") @Column(type="integer") 
         */
        public $ID;

        /**
         * @Column(type="string", length=500)
         */
        public $Content;
    }

?>