2

我有一个原则实体,它被持久化到数据库中,而我从来没有调用过持久化或刷新。

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

这里发生了什么?

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

这是代码(test.php):

<?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!");
?>

在数据库中创建并填充 MyEntity 表:

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");

创建 MyEntity 学说实体(testEntities\MyEntity.php):

<?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;
    }

?>
4

1 回答 1

2

教义手册:9.事务和并发-> 9.1.2。方法 2:明确(在部分底部):

Connection#transactional($func) 和 EntityManager#transactional($func) 之间的区别在于,后者的抽象在事务提交之前刷新 EntityManager,并且在发生异常时也会正确关闭 EntityManager(除了回滚事务)。

所以:EntityManager#transactional($func)在事务提交之前刷新 EntityManager(如果$func调用成功 - 你的情况)。

于 2012-12-19T19:32:15.623 回答