原则2:按实体查找复合主键

时间:2012-04-13 17:43:09

标签: php database doctrine-orm associations doctrine-query

我有两个实体类,ProductOrderEntry,定义如下(为了紧凑而省略了一些注释):

class Product {

   /**
    * @Id
    */
   protected $id;

   /**
    * @Column()
    * @Id
    */
   protected $prodNumber;

   /**
    * @Column()
    * @Id
    */
   protected $group;

   // more cols here
}

class OrderEntry {

   // more cols here

   /**
    * @ManyToOne(targetEntity="Product")
    * @JoinColumns({
    *      @JoinColumn(name="prodNumber", referencedColumnName="prodNumber"),
    *      @JoinColumn(name="group", referencedColumnName="group")
    * })
    */
   protected $Product;
}

现在我想通过其关联的Product与查询构建器找到OrderEntry。对我来说最合乎逻辑的是:

class OrderEntryRepository extends EntityRepository  {

    public function findByProduct($product) {
       $qb = $this->getQueryBuilder('o');
       $qb->where($qb->expr()->eq('o.Product', '?1')
          ->setParameter(1, $product)
          ->setMaxResults(1);
       return $qb->getQuery()->execute(); 
    }
}

然而,这引发了一个例外

的异常
  

具有a的实体的单值关联路径表达式   不支持复合主键。明确命名组件   查询中的复合主键。

如何明确命名组件?我知道我可以通过JOIN来做到这一点,但在这种情况下我对产品毫无用处,只会使查询更加昂贵。

1 个答案:

答案 0 :(得分:1)

您无法避免使用当前映射加入products表:

public function findByProduct($product) {
   $qb = $this->getQueryBuilder('o');
   $qb
      ->join('o.Product', 'p')
      ->where('p.prodNumber = ?1')
      ->setParameter(1, $product->getProdNumber())
      ->andWhere('p.group = ?2')
      ->setParameter(2, $product->getGroup())
   ;
   return $qb->getQuery()->getOneOrNullResult(); 
}

您可以向OrderEntry添加单独的属性,这些属性将使用与JoinColumns相同的列,例如:

/**
 * @Column(name="prodNumber")
 */
protected $prodNumber;

然后你可以在条件中使用它们:

... 
->where('o.prodNumber = ?1')
->setParameter(1, $product->getProdNumber()
...