2011-04-13 120 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