简体   繁体   中英

Doctrine 2: Find by entity with composite primary key

I have two entity classes, Product and OrderEntry , defined like this (some annotations left out for compactness):

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;
}

Now I want to find an OrderEntry by its associated Product with the query builder. The most logical thing for me would be this:

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(); 
    }
}

However, this throws an exception that says

A single-valued association path expression to an entity with a composite primary key is not supported. Explicitly name the components of the composite primary key in the query.

How do I name the components explicitly? I know I could do it with a JOIN, but I have no use for the Product in this case and it would just make the query more expensive.

You can't avoid joining the products table with the current mapping:

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(); 
}

You can add separate properties to OrderEntry, which would use the same columns as the JoinColumns, eg:

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

And then you can use them in conditions:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM