2011-04-13 102 views
36

更新是否有可能在如下類似的方式更新實體:學說2從實體

$data  = new ATest(); // my entity 
$data->id = 1;   // id 1 already exists, I just want to update this row 
$data->name = "ORM Tested"; // changed the name 

$entityManager->persist($data); 
$entityManager->flush(); 

這將插入,改變對象的ID,而不是在數據庫中更新現有行。

+2

你怎麼能手動設置ID? ID不是受保護的財產嗎? – 2014-06-11 12:05:42

+0

不,不,如果你不做它 – Eagle1 2015-02-12 18:58:42

回答

49

我不得不使用

$entityManager->merge($data) 
+9

請注意,你應該把它複製回$數據。即:'$ data = $ entityManager-> merge($ data)' – 2013-02-11 22:46:38

+0

你如何看待這個問題?我在目前的文檔中沒有看到它。也許它自2013年以來發生了變化。http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html#merging-entities – 2016-04-08 03:29:33

+0

@JeroenDeDauw在你引用的鏈接中' // $實體現在引用合併操作返回的完全託管副本。否則$ data將引用實例化,分離或非託管對象。這個過程可以通過'\ Doctrine \ ORM \ UnitOfWork :: doMerge'在2.5中進行驗證,在這裏它創建一個類的新實例,否則從數據庫返回檢索到的實體。 – fyrye 2016-05-02 16:16:18

66

你應該叫合併,而不是堅持:

$data = new MyEntity(); 
$data->setId(123); 
$data->setName('test'); 

$entityManager->merge($data); 
$entityManager->flush(); 
+5

我覺得有人在這裏改變了他的答案,所以我的看起來不再有用了...... – 2014-07-10 07:57:47

+5

他批准了他自己的,有我的upvote! – hattila 2015-06-08 11:21:46

+1

非託管實體需要合併,例如(在我的情況下)實體通過反序列化實例化 – 2017-02-12 12:44:41

13

或者只是得到管理的實體,而不是一個空。

$data = $entityManager->getRepository('ATest')->findOne(1); // ATest is my entitity class 
$data->name = "ORM Tested"; // just change the name 

$entityManager->persist($data); 
$entityManager->flush(); 

如果實體已經被管理,persist()會更新它,而不是插入一個新的。

+6

如果一個實體被管理,調用persist不是必需的,堅持只是告訴教條開始管理一個實體。在這種情況下,刷新就足夠了。 – 2013-08-07 17:46:29

+2

其實,是否需要persist取決於配置 – 2013-09-28 10:37:19

+3

這不是對數據庫的雙重查詢只是爲了更新嗎? – Sejanus 2014-12-05 12:22:35

11

您也可以使用getReference以標識符更新實體屬性而不檢索數據庫狀態。

http://doctrine-orm.readthedocs.org/en/latest/reference/advanced-configuration.html#reference-proxies

這將建立一個簡單的代理通過ID與實體工作,而不是實例化一個new Entity或明確使用find()數據庫,然後可以通過刷新來更新得到的實體。

$data = $entityManager->getReference('ATest', $id); 
$data->setName('ORM Tested'); 
$entityManager->flush(); 

這是用於更新一個實體的OneToManyManyToMany協會特別有用。 EG:$case->addTest($data);

手動設置新實體的標識符通常是不好的做法,即使意圖是更新實體。相反,通常最好讓EntityManager建立適當的標識符。出於這個原因,默認情況下,Doctrine會將標識符作爲私有屬性生成實體,而不使用setter方法。

+0

這是與:: merge的不同之處()? – Aerendir 2015-07-26 23:29:57

+3

'合併'將實體作爲'Managed'附加到實體管理器。在OP案例中需要的原因是該實體沒有被管理(分離)。發生這種情況是因爲它是「實例化的」,並且從未持續/檢索,因爲它已經存在(根據OP)。因此需要更新而不是持久性。所以在OP中,實體管理器試圖堅持新對象,因爲它已經存在,所以無法執行,並且由於新對象不是「管理」的,所以也沒有發生更新。 – fyrye 2015-07-27 13:10:04