内容简介: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:一对多关联缓存》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
An Introduction to Genetic Algorithms
Melanie Mitchell / MIT Press / 1998-2-6 / USD 45.00
Genetic algorithms have been used in science and engineering as adaptive algorithms for solving practical problems and as computational models of natural evolutionary systems. This brief, accessible i......一起来看看 《An Introduction to Genetic Algorithms》 这本书的介绍吧!