Symfony 2 - findall()太多的数据库查询

时间:2015-02-20 12:28:52

标签: symfony doctrine-orm

如果我使用以下代码,Symfony2执行40个数据库查询的原因:

$em = $this->getDoctrine()->getManager();
$records = $em->getRepository('MyWebBundle:Highlight')->findAll();

我认为findAll()方法只返回Highlight实体中的所有项目,而其他实体的关联则替换Proxy对象。但现在findAll()方法获取所有关联实体。

你知道问题出在哪里吗?

的indexAction

public function indexAction() {
    $em = $this->getDoctrine()->getManager();
    $records = $em->getRepository('MyWebBundle:Highlight')->findAll();

    $csrf = $this->get('security.csrf.token_manager');
    $token = $csrf->refreshToken(self::FORM_TOKEN_ID);

    $params = array(
        "data" => array(
            "all" => $records,
        ),
        "token" => $token->getValue(),
        "static" => array(
            "add" => $this->generateUrl("admin_highlight_add"),
            "edit" => $this->generateUrl("admin_highlight_edit"),
            "del" => $this->generateUrl("admin_highlight_del"),
        ),
    );
    $ser = $this->get('jms_serializer');
    $jsonContent = $ser->serialize($params, 'json');

    return array('jsonContent' => $jsonContent);
}

突出显示实体     

namespace My\WebBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;

/**
 * Highlight
 *
 * @JMS\ExclusionPolicy("none")
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="My\WebBundle\Entity\HighlightRepository")
 */
class Highlight {

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="abbreviation", type="string", length=8, unique=true)
     */
    private $abbreviation;

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="string", length=80, nullable=true)
     */
    private $description;

    /**
     * @var string
     *
     * @ORM\Column(name="color", type="string", length=7)
     */
    private $color;

    /**
     * @var ArrayCollection
     * @ORM\OneToMany(targetEntity="Goods", mappedBy="highlight")
     */
    private $goods;

    /**
     * @var ArrayCollection
     * @ORM\OneToMany(targetEntity="Calibration", mappedBy="highlight")
     */
    private $calibrations;

    /**
     * Constructor
     */
    public function __construct() {
        $this->goods = new \Doctrine\Common\Collections\ArrayCollection();
        $this->calibrations = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId() {
        return $this->id;
    }

    /**
     * Set abbreviation
     *
     * @param string $abbreviation
     * @return Highlight
     */
    public function setAbbreviation($abbreviation) {
        $this->abbreviation = $abbreviation;

        return $this;
    }

    /**
     * Get abbreviation
     *
     * @return string 
     */
    public function getAbbreviation() {
        return $this->abbreviation;
    }

    /**
     * Set description
     *
     * @param string $description
     * @return Highlight
     */
    public function setDescription($description) {
        $this->description = $description;

        return $this;
    }

    /**
     * Get description
     *
     * @return string 
     */
    public function getDescription() {
        return $this->description;
    }

    /**
     * Set color
     *
     * @param string $color
     * @return Highlight
     */
    public function setColor($color) {
        $this->color = $color;

        return $this;
    }

    /**
     * Get color
     *
     * @return string 
     */
    public function getColor() {
        return $this->color;
    }

    /**
     * Add goods
     *
     * @param \My\WebBundle\Entity\Goods $goods
     * @return Highlight
     */
    public function addGood(\My\WebBundle\Entity\Goods $goods) {
        $this->goods[] = $goods;

        return $this;
    }

    /**
     * Remove goods
     *
     * @param \My\WebBundle\Entity\Goods $goods
     */
    public function removeGood(\My\WebBundle\Entity\Goods $goods) {
        $this->goods->removeElement($goods);
    }

    /**
     * Get goods
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getGoods() {
        return $this->goods;
    }

    /**
     * Add calibrations
     *
     * @param \My\WebBundle\Entity\Calibration $calibrations
     * @return Highlight
     */
    public function addCalibration(\My\WebBundle\Entity\Calibration $calibrations) {
        $this->calibrations[] = $calibrations;

        return $this;
    }

    /**
     * Remove calibrations
     *
     * @param \My\WebBundle\Entity\Calibration $calibrations
     */
    public function removeCalibration(\My\WebBundle\Entity\Calibration $calibrations) {
        $this->calibrations->removeElement($calibrations);
    }

    /**
     * Get calibrations
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getCalibrations() {
        return $this->calibrations;
    }

}

突出显示存储库为空

2 个答案:

答案 0 :(得分:2)

我认为问题来自序列化程序。由于你序列化了一个highliths,它们每个都有自己的属性序列化,这意味着将对已经序列化的已撤销商品执行延迟查询。

然后,您应该通过添加注释突出显示商品属性来阻止此行为

use ...
use JMS\SerializerBundle\Annotation\ExclusionPolicy;
use JMS\SerializerBundle\Annotation\Exclude;

/**
 * ...
 * @ExclusionPolicy("none")
 */
 class Highlight
{

   /**
    * ...
    * @Exclude
    */
   private $goods;

}

您可以从JMSSerializer doc

获取有关排除任务的更多详细信息

答案 1 :(得分:0)

findAll本身不会执行很多查询。通过getter访问相关实体时执行查询。由于关系没有得到热切关注,所以当你进行关系时,他们会第一时间获取关系。

我认为序列化程序会访问所有子项以发送您的对象。

请参阅Doctrine documentation

  

只要您有一个托管实体实例,就可以遍历   并使用配置为LAZY的该实体的任何关联,如果   他们已经在记忆中了。 Doctrine会自动加载   通过延迟加载的概念按需关联对象。

要防止这种情况,要么禁用子序列化,要么使用获取EAGER或构建DQL查询,该查询会预取所有子项以及父项,如(只是示例,无效DQL)

SELECT Highlight, Good, Calibration
FROM Highlights Highlight
LEFT JOIN  Highlight.googs Good
LEFT JOIN  Goog.calibrations Calibration
WHERE ...