摘要:哪个更快:更新/刷新实体列表,或在每个实体上运行查询生成器更新?
我们在 Doctrine ORM(2.3 版)中有以下情况。
我们有一个看起来像这样的表
cow
wolf
elephant
koala
我们想用这张表对一个虚构农场的报告进行排序。问题是用户希望客户订购动物(例如考拉、大象、狼、牛)。现在存在使用 CONCAT 或 CASE 为 DQL 添加权重的可能性(例如 0002wolf、0001elephant)。以我的经验,这要么很难构建,而且当我让它工作时,结果集是一个数组而不是一个集合。
因此,为了解决这个问题,我们为每条记录添加了一个“权重”字段,并且在运行选择之前,我们为每条记录分配了一个权重:
$animals = $em->getRepository('AcmeDemoBundle:Animal')->findAll();
foreach ($animals as $animal) {
if ($animal->getName() == 'koala') {
$animal->setWeight(1);
} else if ($animal->getName() == 'elephant') {
$animal->setWeight(2);
}
// etc
$em->persist($animal);
}
$em->flush();
$query = $em->createQuery(
'SELECT c FROM AcmeDemoBundle:Animal c ORDER BY c.weight'
);
这完美地工作。为了避免竞争条件,我们在事务块中添加了这个:
$em->getConnection()->beginTransaction();
// code from above
$em->getConnection()->rollback();
这更加强大,因为它可以处理生成相同报告的多个用户。或者,可以像这样对实体进行加权:
$em->getConnection()->beginTransaction();
$qb = $em->createQueryBuilder();
$q = $qb->update('AcmeDemoBundle:Animal', 'c')
->set('c.weight', $qb->expr()->literal(1))
->where('c.name = ?1')
->setParameter(1, 'koala')
->getQuery();
$p = $q->execute();
$qb = $em->createQueryBuilder();
$q = $qb->update('AcmeDemoBundle:Animal', 'c')
->set('c.weight', $qb->expr()->literal(2))
->where('c.name = ?1')
->setParameter(1, 'elephant')
->getQuery();
$p = $q->execute();
// etc
$query = $em->createQuery(
'SELECT c FROM AcmeDemoBundle:Animal c ORDER BY c.weight'
);
$em->getConnection()->rollback();
问题:
1)这两个例子中哪一个会有更好的表现?
2)考虑到我们需要一个集合,是否有第三种或更好的方法来做到这一点?
请记住,这只是一个示例——在内存中对结果集进行排序不是一个选项,它必须在数据库级别完成——真正的语句是一个 10 表连接和 5 个 orderby。