内容简介: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大难题
- 缓存穿透和缓存击穿处理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
jQuery in Action
Bear Bibeault、Yehuda Katz / Manning Publications / 2008-2-17 / USD 39.99
A good web development framework anticipates what you need to do and makes those tasks easier and more efficient; jQuery practically reads your mind. Developers of every stripe-hobbyists and professio......一起来看看 《jQuery in Action》 这本书的介绍吧!