Doctrine2查询需要子查询的位置

时间:2011-11-17 10:39:39

标签: mysql doctrine-orm

首先介绍本例中使用的实体:

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。通过使用最新的created_at查看OrderStatus,可以计算出实际的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对象并手动找出哪个是最新的,还是可以预选?

1 个答案:

答案 0 :(得分:0)

我找到了一种不太适合我的方式,但它并不需要对我的应用程序进行任何更改,所以只要我找不到它,它就可以了。更好的解决方案。

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

所以我的Order-Object看起来像这样:

/**
 * @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!
}

我的订单状态将如下所示:

/**
 * @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!
}

请注意OrderStatus中的, cascade={"persist"},以便在持久保存OrderStatus时也会保留订单,否则状态将被设置,但不会存储!

这个解决方案的另一方面是我现在通过调用$order->getStatus()来获取OrderStatus,而不必查询数据库中的状态以及我能够$repository->findByStatus(0)。另一方面,当状态字段由于某些错误而改变时,数据将不一致。

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