0

我正在使用 symfony2 构建 Web 应用程序。我正在使用 Doctrine 作为数据库引擎。我将需要使用一些复杂的数据库查询来从 mysql 库中接收数据。我发现(如果我错了,请纠正我)是:

  1. DQL - 在对对象(getter、setter 等)进行操作的情况下很有用。不幸的是,如果我的应用程序使用复杂的 sql 查询(许多左连接、内连接等),它就不是很有帮助。
  2. 本机 SQL - 我不确定这种方法。不能对对象进行操作吗?我很难创建连接查询。
  3. RAW SQL - 任何 sql 查询都是可能的,但我不能使用对象。
4

1 回答 1

2

即使在您的应用程序和数据库之间有 ORM 层,有时您也可能需要编写原始 SQL 查询;例如,如果您正在生成有关应用程序使用情况的报告,或者您正在计算中间数据等。

但是,在每种情况下,您都应该问自己,使用对象而不是原始数据是否更合适。在许多情况下,人们认为如果不直接进入数据库级别就无法获得结果,但他们可能会惊讶地发现,使用像 Doctrine 这样的现代 ORM 确实可以做很多事情。

在 Doctrine 中,连接由关联表示,系统的主要优点之一是您可以通过对象而不是原始 SQL 与关联进行交互的方式。

考虑下面的“复杂”查询(好吧,它真的没那么复杂):

SELECT foo.*, bar.*
FROM foo
LEFT JOIN bar ON foo.foo_id = bar.foo_id
WHERE foo.name = "x"

在 Doctrine 中,您可以使用实体对此进行建模。例如,一个片段:

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="foo")
 */
class Foo
{
  /**
   * @ORM\Id
   * @ORM\Column(name="foo_id", type="integer")
   * @ORM\GeneratedValue
   */
  private $id;

  /**
   * @ORM\Column(name="foo_name", type="string", length=32)
   */
  private $name;

  /**
   * @ORM\OneToMany(targetEntity="Bar", mappedBy="foos")
   */
  private $bars;

  // more code ...

}

还有一个:

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="bar")
 */
class Bar
{
  /**
   * @ORM\Id
   * @ORM\Column(name="bar_id", type="integer")
   * @ORM\GeneratedValue
   */
  private $id;

  /**
   * @ORM\Column(name="bar_name", type="string", length=32)
   */
  private $name;

  /**
   * @ORM\ManyToOne(targetEntity="Foo", inversedBy="bars")
   * @ORM\JoinColumn(name="foo_id", referencedColumnName="foo_id")
   */
  private $foo;

  // more code ...

}

现在,在 DQL 中,我们可以重写原始查询:

SELECT f, b
FROM \Your\Namespace\Foo f
LEFT JOIN f.bars b
WHERE f.name = "x"

此查询将生成一个或多个 Foo 对象,以及与每个对象关联的任何 Bar 对象,所有这些对象都只需要对数据库的单个查询。使用这种模式,您应该能够使用对象对绝大多数有用的 SQL 查询进行建模,使它们的关系自然且易于理解。

另一件值得注意的事情是,上面的 DQL 查询实际上被称为“获取连接”,因为它会同时处理被请求的 Foo 对象和与之关联的任何 Bar 对象。一个更简单的查询版本是:

SELECT f
FROM \Your\Namespace\Foo f
WHERE f.name = "x"

这将在第一个查询中仅水合 Foo 对象,不执行任何连接。但是,您仍然可以访问关联的 Bar 对象(例如$foo->getBars()),并且 Doctrine 将根据需要自动获取关联的数据(这称为“延迟加载”)。在所有情况下,您都可以自由决定是否要为实体的部分或全部对象图进行水合,或者只是检索顶级数据并允许 Doctrine 根据需要加载数据。

在Doctrine Association Mapping 文档中有很多关于此的信息。

于 2013-10-21T01:03:04.637 回答