2013-06-11 14 views
5

私はJPA基準のAPIを使用して、以下のような何かを達成しようとしている:スーパークラスが照会されるCriteriaQueryのサブクラス固有のフィールドを参照する方法はありますか?

SELECT b FROM Box b JOIN SpecialItem s WHERE s.specialAttr = :specialAttr 

は、オブジェクトが

ボックス

@Entity 
public class Box implements Serializable { 
    ... 
    @ManyToOne 
    @JoinColumn(name = "item_id") 
    Item item; 
    ... 
} 

項目

@Entity 
@Inheritance(strategy = InheritanceType.JOINED) 
public class Item implements Serializable { 
    @Id 
    private String id; 
    ... 
} 
です specialAttrはクラスアイテムのメンバーではないので、

SpecialItem

@Entity 
public class SpecialItem extends Item { 
    private String specialAttr; 
    ... 
} 

私の試み

EntityManager em = getEntityManager(); 
CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery cq = cb.createQuery(Box.class); 
Root from = cq.from(Box.class); 

// Nothing to specify SpecialItem over Item!  
Join join = from.join("item", JoinType.LEFT); 

// java.lang.IllegalArgumentException: Unable to 
// resolve attribute [specialAttr] against path [null]  
Path p = join.get("specialAttr"); 

Predicate predicate = cb.equal(p, "specialValue"); 
cq.where(predicate); 

は驚くことではないが、それは例外をスローします。

SpecialItemを含むBoxのすべてを返すにはどうすればいいですか?SpecialItem.specialAttrには値がありますか?

答えて

10

JPA 2.1を使用している場合、あなたは私がちょうど生成されたメタモデルと基準APIのためにクリスの答えを拡張したい

"SELECT b FROM Box b WHERE TREAT(b.item as SpecialItem).specialAttr = :specialAttr" 

または

CriteriaQuery<Box> q = cb.createQuery(Box.class); 
Root<Box> box= q.from(Box.class); 
Join<Box, Item > order = box.join("item"); 
q.where(cb.equal(cb.treat(order, SpecialItem.class).get("specialAttr"), 
    qb.parameter(String.class, "specialAttr"))); 
q.select(Box); 
+0

ありがとうございますが、私はCriteria APIを使用してこれをどうやって行いますか? – Alex

+3

本当にありがとうございます!興味があれば、JPA 2.0で解決できるのでしょうか? – Alex

+0

はい、しかし余分な結合を引き起こす可能性があります。あなたは結合を明示的にする必要があり、逆にクエリを構築する必要があります。何かのような "選択bボックスb、SpecialtyItem si b.item = siとsi.specialAttr =:specialAttr" – Chris

3

を使用する場合があります。

CriteriaQuery<Box> q = cb.createQuery(Box.class); 
Root<Box> box= q.from(Box.class); 
Join<Box, Item> order = box.join(Box_.item); 
q.where(cb.equal(cb.treat(order, SpecialItem.class).get(SpecialItem_.specialAttr), "searchValue"); 
q.select(Box); 
+0

ありがとう!それは本当に明らかではありませんでした! – dikkini

関連する問題