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 表现得相当好。无需真正担心微优化。