为什么空交易会持续存在我的实体(学说)?

时间:2022-09-14 06:50:00

I have a doctrine entity which is being persisted to the database without me ever calling persist or flush.

我有一个教义实体,它被持久存储到数据库中,而我没有调用persist或flush。

I've managed to reproduce the problem quite simply below. As you will see, this script loads a row from a database table called MyEntity and obtains a php object with the row's fields as attributes. The script then changes one of the attributes, but does not call persist or flush. Then the script create an empty transaction which does nothing. Oddly, this makes the object persist in the sense that the changes made to the php object are also made in the database. I wouldn't have expected this script to make any changes to the database.

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

What is happening here?

这里发生了什么?

Note that if I remove the empty transaction, the problem dissapears and no change is made to the database.

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

Here is the code (test.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!");
?>

Create and fill MyEntity table in the database:

在数据库中创建并填充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");

Create MyEntity doctrine Entity (testEntities\MyEntity.php):

创建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;
    }

?>

1 个解决方案

#1


2  

Doctrine manual: 9. Transactions and Concurrency -> 9.1.2. Approach 2: Explicitly (at section bottom):

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

The difference between Connection#transactional($func) and EntityManager#transactional($func) is that the latter abstraction flushes the EntityManager prior to transaction commit and also closes the EntityManager properly when an exception occurs (in addition to rolling back the transaction).

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

So: EntityManager#transactional($func) flushes the EntityManager prior to transaction commit (if $func call was successful - your case).

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

#1


2  

Doctrine manual: 9. Transactions and Concurrency -> 9.1.2. Approach 2: Explicitly (at section bottom):

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

The difference between Connection#transactional($func) and EntityManager#transactional($func) is that the latter abstraction flushes the EntityManager prior to transaction commit and also closes the EntityManager properly when an exception occurs (in addition to rolling back the transaction).

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

So: EntityManager#transactional($func) flushes the EntityManager prior to transaction commit (if $func call was successful - your case).

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