内容简介: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大难题
- 缓存穿透和缓存击穿处理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML5与CSS3权威指南(上册) (第3版)
陆凌牛 / 机械工业出版社 / 2015-9-1 / CNY 89.00
本书是HTML 5与CSS 3领域公认的标杆之作,被读者誉为“系统学习HTML 5与CSS 3的最佳著作”和“Web前端工程师案头必备图书之_”。 前两版累计印刷超过15次,网络书店评论超过8000条,98%以上的评论都是五星级的好评。不仅是HTML 5与CSS 3图书领域当之无愧的领头羊,而且在整个原创计算机图书领域是佼佼者。 第3版首先从技术的角度根据最新的HTML 5和CSS 3......一起来看看 《HTML5与CSS3权威指南(上册) (第3版)》 这本书的介绍吧!
JS 压缩/解压工具
在线压缩/解压 JS 代码
正则表达式在线测试
正则表达式在线测试