学说分离,缓存和合并

时间:2012-11-14 02:47:27

标签: php doctrine doctrine-orm

我在学说2.3。我有以下查询:

$em->createQuery('
    SELECT u, c, p
    FROM Entities\User u
    LEFT JOIN u.company c
    LEFT JOIN u.privilege p
    WHERE u.id = :id
')->setParameter('id', $identity)

然后我接受它,得到结果(这是一个数组,我只取第一个元素),然后运行detach $em->detach($result);

当我从缓存中获取时(使用Doctrine的APC缓存驱动程序),我这样做:

$cacheDriver = new \Doctrine\Common\Cache\ApcCache();
if($cacheDriver->contains($cacheId))
{
    $entity = $cacheDriver->fetch($cacheId);
    $em->merge($entity);
    return $entity;
}

我希望这会重新启用实体上的关系加载,因为除了该查询中显示的内容之外,还有许多其他关系绑定到User对象。

我正在尝试创建一个像这样的新实体:

$newEntity = new Entities\ClientType();
$newEntity['param'] = $data;
$newEntitiy['company'] = $this->user['company'];
$em->persist($newEntity);
$em->flush();

当我这样做时,我收到一个错误:

A new entity was found through the relationship 'Entities\ClientType#company' that was not configured to cascade persist operations for entity:
Entities\Company@000000005d7b49b500000000dd7ad743. 
To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). 
If you cannot find out which entity causes the problem implement 'Entities\Company#__toString()' to get a clue.

当我在缓存中使用的用户实体下不使用公司实体时,这很好用。有没有办法让这项工作成功,所以每次我想在与新实体的关系中使用它时,我都不必从数据库中重新获取公司实体?

修改 这就是我在处理这两种关系的用户实体中所拥有的:

/**
    * @ManyToOne(targetEntity="Company" , inversedBy="user", cascade={"detach", "merge"})
    */
    protected $company;

    /**
    * @ManyToOne(targetEntity="Privilege" , inversedBy="user", cascade={"detach", "merge"})
    */
    protected $privilege;

我仍然遇到同样的错误。

第二次修改 尝试$em->contains($this->user);$em->contains($this->user['company']);都会返回false。哪个听起来......错了。

1 个答案:

答案 0 :(得分:13)

合并用户时,您希望合并关联的公司和权限,是否正确?

此过程称为级联:

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations

在您的用户实体中,cascade={"merge"}@ManyToOne注释(或您正在使用的其他类型的关联定义)放入$company$privilege

如果您希望分离呼叫也是级联的(建议使用),请输入cascade={"detach", "merge"}

p.s。:不要在一个关联的两边放置这样的级联,你将创建一个无限循环;)

修改

这段代码:

$entity = $cacheDriver->fetch($cacheId);
$em->merge($entity);                      // <-
return $entity;

应该是:

$entity = $cacheDriver->fetch($cacheId);
$entity = $em->merge($entity);            // <-
return $entity;

具有merge()的东西是它将您作为参数传递的实体保持不变,并返回表示该实体的托管版本的 new 对象。所以你想使用返回值,而不是你传递的参数。