我有一個教條實體正在被持久保存到數據庫中,我沒有調用persist或flush。爲什麼空的事務會持續我的實體(原則)?
我設法在下面簡單地重現了這個問題。正如你將會看到的,這個腳本從一個名爲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;
}
?>
這可能會讓EntityManager浮躁,但是如果我從來沒有調用persist,它應該不會將任何內容保存到數據庫,如果它? – Shawn
不,你錯了。這取決於跟蹤策略。閱讀手冊中的[Tracking Policies](http://docs.doctrine-project.org/en/latest/reference/change-tracking-policies.html#change-tracking-policies)。默認策略是Deferred Implicit。 _有了這個策略,Doctrine在提交時通過屬性和屬性的比較來檢測變化,並且還檢測對其他被管理實體引用的實體或新實體的變化(「通過可達性持久化」)_。 –
如果您將'@ChangeTrackingPolicy(「DEFERRED_EXPLICIT」)'註釋添加到'class MyEntity',那麼您的較高評論將變爲true,Doctrine必須停止保存您示例的更改。 –