我正在使用symfony2构建Web应用程序。我正在使用Doctrine作为数据库引擎。我需要使用一些复杂的数据库查询来从mysql库中恢复数据。我发现的(如果我错了请纠正我)是:
答案 0 :(得分: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根据需要加载数据。