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