内容简介:http://stackoverflow.com/questions/36978702/doctrine-2-cache-in-one-to-many-associations
我正在尝试使用通用软件包中的教条缓存,但是我无法使用一对多,多对一的注册.我稍后会解释一下我要做的事情.
我的配置:
'configuration' => array( 'orm_default' => array( 'metadata_cache' => 'filesystem', 'query_cache' => 'filesystem', 'result_cache' => 'filesystem', 'hydration_cache' => 'filesystem', ) ),
我的实体
class Category { /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") * * @var string */ protected $id; /** * @var string * * @ORM\Column(name="name", type="string", length=100, nullable=false) */ protected $name; /** * @var integer * * @ORM\ManyToOne(targetEntity="Category", inversedBy="childrenId", fetch="EAGER") * @ORM\JoinColumn(name="parent_id", referencedColumnName="id") */ protected $parentId; /** * @ORM\OneToMany(targetEntity="Category", mappedBy="parentId", fetch="EAGER") */ protected $childrenId; }
我的DQL
$result = $this->em->createQueryBuilder()->select('c') ->from('App\Entity\Category', 'c') ->where('c.parentId IS NULL') ->orderBy('c.priority', 'ASC') ->getQuery() ->setFetchMode("App\Entity\Category", "parentId", \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER); ->useResultCache(true, 900, 'categories') ->getResult();
我有28个类别,其中15个有parentId.
以上查询执行29个 SQL 查询,但Doctrine仅存储在缓存中1,所以当我再次运行这个查询时,它执行28个查询.
任何想法我做错了什么?缺少一些缓存配置?在DQL中缺少一些方法?我想缓存所有查询不仅仅是一个主要的查询.
编辑
我想在循环中使用查询结果,如下所示:
foreach($result as $row) { $categories[]['attr'] = $row->getAttribute()->getName(); $categories[]['value'] = $row->getAttribute()->getValue(); }
但是这种方式缓存将无法正常工作,所以目前我正在使用:
foreach($result as $row) { $attributes = $this->em->createQueryBuilder()->select('c, a.name, a.value') ->from('App\Entity\Category', 'c') ->innerJoin('App\Entity\Attribute', 'a', 'WITH', 'a.id = c.attribute') ->where('c.id = :catId') ->setParameter('catId', $row['id']) ->getQuery() ->useResultCache(true, 900, $categoryName.'-attributes') ->getArrayResult(); }
但是我宁愿在数组上处理对象,但是如果我使用对象并且它具有关联,那么这个关联将不会被缓存.所以理想的方法是缓存对象ALL他的关联.
关联提取模式
您所提供的查询只能提取“父类”类别实体,该实体可以通过未初始化的子项来收集.当访问该集合(通过迭代这些孩子)时,Doctrine将加载集合,从而执行另一个查询.它会对第一个查询所包含的所有父类别执行此操作.
将提取模式设置为EAGER只会更改这些查询完成的时刻.教义将在保持父类别之后立即执行,直到您访问该集合才能等待(如使用提取模式LAZY).但它仍然会执行这些查询.
获取连接查询
告诉Doctrine与孩子查询和合并类别的最简单的方法是做一个“fetch join”查询:
$queryBuilder = $this->em->createQueryBuilder(); $queryBuilder ->select('p', 'c') // [p]arent, [c]hild ->from('App\Entity\Category', 'p') ->leftJoin('p.children', 'c') ->where('p.parent IS NULL') ->orderBy('p.priority', 'ASC'); $query = $queryBuilder->getQuery(); $query ->useResultCache(true, 900, 'categories') $result = $query->getResult();
请注意这里的select()和leftJoin()调用.
您也不需要更改关联的提取模式(通过调用setFetchMode()),因为查询本身会告诉Doctrine来执行所需的操作.
这样做的结果是,如果Doctrine尚未缓存(或缓存为陈旧),则Doctrine将执行1个查询,如果缓存(仍然是新鲜的),则会执行0个查询.
假设
属性$parentId(在类别中)被重命名为$parent.此属性将包含父类别实体,或null,但不包含id.
$childrenId的属性重命名为$children.此属性将包含一个类别实体(可能为空)的集合,但不包含ids的集合(或数组),并且绝对不会有一个id.
我上面提出的查询考虑了这些重命名.
我完全忽略了一个事实,即你的“编辑”一个新的属性实体刚刚成立.这与你的问题无关,或者这个答案是呃.
更多的水平
看起来/听起来像你的类别只使用2级(父母和孩子).当您引进更多级别(孙子等)时,阅读此模型可能会非常低效.
当进行3级或更多级别时,您可能需要查看 Nested Set model .写入次数较重,但对读取进行了高度优化.
DoctrineExtensions 图书馆支持这一点,还有一个 Symfony Bundle .
http://stackoverflow.com/questions/36978702/doctrine-2-cache-in-one-to-many-associations
以上所述就是小编给大家介绍的《symfony – 教义2:一对多关联缓存》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 轻松学会HTTP缓存(强缓存,协商缓存)
- 常见面试题之缓存雪崩、缓存穿透、缓存击穿
- HTTP缓存 - 强缓存/协商缓存/浏览器刷新
- mybatis教程--查询缓存(一级缓存二级缓存和整合ehcache)
- 如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
- 缓存穿透和缓存击穿处理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
企业应用架构模式
Martin Fowler、王怀民、周斌 / 王怀民、周斌 / 机械工业出版社 / 2004-7 / 49.00元
本书作者是当今面向对象软件开发的权威,他在一组专家级合作者的帮助下,将40多种经常出现的解决方案转化成模式,最终写成这本能够应用于任何一种企业应用平台的、关于解决方案的、不可或缺的手册。本书获得了2003年度美国软件开发杂志图书类的生产效率奖和读者选择奖。本书分为两大部分。第一部分是关于如何开发企业应用的简单介绍。第二部分是本书的主体,是关于模式的详细参考手册,每个模式都给出使用方法和实现信息,并一起来看看 《企业应用架构模式》 这本书的介绍吧!
CSS 压缩/解压工具
在线压缩/解压 CSS 代码
RGB转16进制工具
RGB HEX 互转工具