原则分离、缓存和合并 [英] Doctrine detaching, caching, and merging

查看:35
本文介绍了原则分离、缓存和合并的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Doctrine 2.3.我有以下查询:

I'm on Doctrine 2.3. I have the following query:

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

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

I then take that, get the result (which is an array, I just take the first element), and run detach $em->detach($result);.

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

When I go to fetch from the cache (using Doctrine's APC cache driver), I do:

$cacheDriver = new DoctrineCommonCacheApcCache();
if($cacheDriver->contains($cacheId))
{
    $entity = $cacheDriver->fetch($cacheId);
    $em->merge($entity);
    return $entity;
}

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

My hope was that this would re-enable the relationship loading on the entity as there are many other relationships tied to the User object other than what's shown in that query.

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

I'm trying to create a new entity like such:

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

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

When I do this, I get an error:

A new entity was found through the relationship 'EntitiesClientType#company' that was not configured to cascade persist operations for entity:
EntitiesCompany@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 'EntitiesCompany#__toString()' to get a clue.

当我不使用从缓存中获得的用户实体下的公司实体时,这很好用.有什么方法可以使这项工作,这样我就不必每次想在与新实体的关系中使用它时都从数据库中重新获取公司实体?

This works just fine when I don't use the company entity under the user entity that I got from cache. Is there any way to make this work so I don't have to refetch the company entity from the database every time I want to use it in a relationship with a new entity?

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

This is what I have in my User entity dealing with these two relationships:

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

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

我仍然遇到同样的错误.

I am still getting the same error.

第二次修改:尝试 $em->contains($this->user);$em->contains($this->user['company']);代码> 都返回 false.听起来……不对.

Second edit: Trying a $em->contains($this->user); and $em->contains($this->user['company']); both return false. Which sounds... wrong.

推荐答案

在合并用户时,您希望关联的公司和权限也合并,对吗?

When merging a User, you want the associated Company and Privilege to be merged as well, correct?

这个过程称为级联:

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

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

In your User entity put cascade={"merge"} in the @ManyToOne annotation (or another type of association-definition you are using) for $company and $privilege.

如果您也希望分离调用也被级联(推荐),请输入 cascade={"detach", "merge"}.

And if you want the detach call to be cascaded too (which is recommended), put in cascade={"detach", "merge"}.

p.s.:不要把这样的级联放在一个关联的两侧,你会创建一个无限循环;)

p.s.: Don't put such cascades on both sides of one association, you'll create an endless loop ;)

这段代码:

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

应该是:

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

merge() 的作用在于,它使您作为参数传递的实体保持不变,并返回一个表示实体托管版本的 new 对象.所以你想使用返回值,而不是你传递的参数.

The thing with merge() is that it leaves the entity you pass as an argument untouched, and returns a new object that represents the managed version of the entity. So you want to use the return-value, not the argument you passed.

这篇关于原则分离、缓存和合并的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆