Doctrine 2 保存具有可能关系的实体
Doctrine 2 saving Entity with possible relations
我正在尝试保存一个实体,它可能已经存在也可能不存在,并且可能有也可能没有一两个关系(下面的代码)。我当前的方法会导致错误,我很确定我可以自己想出一些 workarounds/hacks,但我对正确的 "official" 方法感兴趣。
我现在正在尝试的是:
$entity = new myEntity();
if ( !empty($id) )
{
$entity->setId($id);
}
$entity->setLocationId($relation_id); //may or may not be null, if not null it's always an already existing location entry in a different table, i.e. not a new
$entity = $entity_manager->merge($entity);
$entity_manager->flush();
目前 Doctrine 抱怨 Location 是一个没有 ID 的新实体,并且政策不允许自动生成 ID。 Policy确实是这样,但是我根本没有添加Location实体,我使用setLocationId()自动生成的方法,它添加了精确存在的Location的ID,所以我有点困惑。
编辑:当位置 id 不为 null 而是一个真实的、现有的(在数据库中)位置的 id 时,我得到了学说错误。
模型:
Location:
type: entity
table: locationstable
id:
my-id-column:
type: string
fields:
some fields
oneToMany:
myEntities:
targetEntity: myEntity
mappedBy: location
cascade: ["persist", "merge"]
尝试查找位置记录并添加到实体中:
$entity = new myEntity();
if ( !empty($id) )
{
$entity->setId($id);
}
//$entity->setLocationId($relation_id); //may or may not be null, if not null it's always an already existing
$location = $locationRepository->find($relation_id);
$entity->setLocation($location);
location entry in a different table, i.e. not a new
$entity = $entity_manager->merge($entity);
$entity_manager->flush();
如果您打算使用 Doctrine 2 的 ORM,那么您确实需要按设计使用它。这意味着使用对象而不是 id。如果您对这种方法不满意,请切换到某种活动记录实现。
//For your case, start by seeing if there is an existing entity:
// This eliminates all the merge nonsense
$entity = $entityManager->getRepository('EntityClassName')->find($entityId);
if (!$entity)
{
$entity = new Entity();
/* Only do this is you are not autogenerating id's
* However, it does raise the question of how you know what the id should be if the entity
* if the entity does not yet exist?
*/
$entity->setId($id);
// Persist the new entity
$entityManager->persist($entity);
}
// Now get a reference to the location object which saves loading the entire location
// which optimizes things a tiny (probably unnoticeable) bit
$location = $entityManager->getReference('LocationClassName',$locationId);
$entity->setLocation($location);
// And flush changes
$entityManager->flush();
再说一次,如果您觉得这太复杂或使用了太多查询,那么请不要使用 Doctrine 2。您将不断地与它作斗争。在实践中,Doctrine 2 表现得相当好。无需真正担心微优化。
我正在尝试保存一个实体,它可能已经存在也可能不存在,并且可能有也可能没有一两个关系(下面的代码)。我当前的方法会导致错误,我很确定我可以自己想出一些 workarounds/hacks,但我对正确的 "official" 方法感兴趣。
我现在正在尝试的是:
$entity = new myEntity();
if ( !empty($id) )
{
$entity->setId($id);
}
$entity->setLocationId($relation_id); //may or may not be null, if not null it's always an already existing location entry in a different table, i.e. not a new
$entity = $entity_manager->merge($entity);
$entity_manager->flush();
目前 Doctrine 抱怨 Location 是一个没有 ID 的新实体,并且政策不允许自动生成 ID。 Policy确实是这样,但是我根本没有添加Location实体,我使用setLocationId()自动生成的方法,它添加了精确存在的Location的ID,所以我有点困惑。
编辑:当位置 id 不为 null 而是一个真实的、现有的(在数据库中)位置的 id 时,我得到了学说错误。
模型:
Location:
type: entity
table: locationstable
id:
my-id-column:
type: string
fields:
some fields
oneToMany:
myEntities:
targetEntity: myEntity
mappedBy: location
cascade: ["persist", "merge"]
尝试查找位置记录并添加到实体中:
$entity = new myEntity();
if ( !empty($id) )
{
$entity->setId($id);
}
//$entity->setLocationId($relation_id); //may or may not be null, if not null it's always an already existing
$location = $locationRepository->find($relation_id);
$entity->setLocation($location);
location entry in a different table, i.e. not a new
$entity = $entity_manager->merge($entity);
$entity_manager->flush();
如果您打算使用 Doctrine 2 的 ORM,那么您确实需要按设计使用它。这意味着使用对象而不是 id。如果您对这种方法不满意,请切换到某种活动记录实现。
//For your case, start by seeing if there is an existing entity:
// This eliminates all the merge nonsense
$entity = $entityManager->getRepository('EntityClassName')->find($entityId);
if (!$entity)
{
$entity = new Entity();
/* Only do this is you are not autogenerating id's
* However, it does raise the question of how you know what the id should be if the entity
* if the entity does not yet exist?
*/
$entity->setId($id);
// Persist the new entity
$entityManager->persist($entity);
}
// Now get a reference to the location object which saves loading the entire location
// which optimizes things a tiny (probably unnoticeable) bit
$location = $entityManager->getReference('LocationClassName',$locationId);
$entity->setLocation($location);
// And flush changes
$entityManager->flush();
再说一次,如果您觉得这太复杂或使用了太多查询,那么请不要使用 Doctrine 2。您将不断地与它作斗争。在实践中,Doctrine 2 表现得相当好。无需真正担心微优化。