2011-11-17 49 views
0

让我先介绍一下本例中使用的实体:Doctrine2查询哪里会需要子查询

Order (_order in mysql) 
    $id (primary key, auto increment) 
OrderStatus (order_status in mysql) 
    $id (primary key, auto increment) 
    $order (storing the order object it is related to, named order_id in mysql) 
    $statuscode (Storing the integer code) 
    $created_at (Storing the datetime of creation) 

的关系是Order n:1 OrderStatus。对于每个状态更改,我使用新的状态码创建一个新的OrderStatus。所以对于一个订单,可以有许多OrderStatus。实际的OrderStatus可以通过查看具有最新的created_at的OrderStatus来计算出来。

我现在想要获取所有状态为0的对象。在SQL中,我的查询如下所示:

SELECT o.id,os.statuscode,os.created_at 
FROM `_order` o 
LEFT JOIN `order_status` os ON o.id = os.order_id 
WHERE os.created_at = (SELECT MAX(created_at) 
         FROM order_status 
         WHERE order_id = os.order_id); 

我可以在DQL中做这样的查询吗?还是必须使用对象?如果是这样,我是否需要阅读所有OrderStatus对象并手动确定哪一个是最新的对象,或者我可以以某种方式预选?

回答

0

我想出了一种并不完全符合我的要求的方式,但它不需要对应用程序进行任何更改,所以只要没有找到更好的解决方案就没关系。

我要做的是我将直接在订单中存储实际状态。通过LifecycleCallbacks,一旦与其相关的OrderStatus被创建,我将立即更新订单。

所以我的订单对象看起来是这样的:

/** 
* @ORM\Entity 
* @ORM\Table(name="_order") 
*/ 
class Order{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    //.. 

    /** 
    * @ORM\Column(type="smallint", nullable=false) 
    */ 
    protected $status = -1; 

    // Getter and Setter! 
} 

我OrderStatus看起来就像这样:

/** 
* @ORM\Entity 
* @ORM\Table(name="order_status") 
* @ORM\HasLifecycleCallbacks 
*/ 
class OrderStatus{ 

    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    /** 
    * @ORM\ManyToOne(targetEntity="Order", inversedBy="order_status", cascade={"persist"}) 
    * @ORM\JoinColumn(name="order_id", referencedColumnName="id", nullable=false) 
    */ 
    protected $order; 

    /** 
    * @ORM\Column(type="smallint", nullable=false) 
    */ 
    protected $statuscode; 

    // .. 

    /** 
    * @ORM\prePersist 
    */ 
    public function prePersist(){ 
    $this->order->setStatus($this->statuscode); 
    } 

    // Getter and Setter! 
} 

心灵的, cascade={"persist"}的OrderStatus内使订单也将持续时OrderStatus被持久化,否则状态将被设置,但不被存储!

这个解决方案的好处是,我现在通过调用$order->getStatus()来获得OrderStatus,而不必查询数据库的状态,并且我能够做到$repository->findByStatus(0)。另一方面,由于某种错误导致状态字段发生变化的时刻,数据将不一致。

如上所述,如果您有一个解决方案,我不需要额外的字段来存储状态,请发布!我对更好的解决方案非常感兴趣!