2016-03-22 8 views
0

をサブ属性I定義されたテーブルに、このようにマッピングエンティティがあります。のコレクション内の属性を検索するJPA criteriaBuilderを使用する方法

@Entity 
@Table(name = "cmmn_calendar_evnt") 

public class CommonCalendarEvent implements java.io.Serializable 
{ 
    private Integer      cevId; 
    private Set<CommonCalendarEventPart> commonCalendarEventParts = new HashSet<CommonCalendarEventPart>(0) 

@Id 
    @GeneratedValue(strategy = IDENTITY) 
    @Column(name = "CEV_ID", unique = true, nullable = false) 
    public Integer getCevId() 
    { 
     return this.cevId; 
    } 

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "commonCalendarEvent") 
    public Set<CommonCalendarEventPart> getCommonCalendarEventParts() 
    { 
     return this.commonCalendarEventParts; 
    } 
} 

とCommonCalendarEventPartは次のように定義されています。

@Entity 
@Table(name = "cmmn_calendar_evnt_part") 

public class CommonCalendarEventPart implements java.io.Serializable 
{ 

    private static final long serialVersionUID = 1L; 
    private Integer    ceeId; 
    private CommonCalendarEvent commonCalendarEvent; 
    private PartParticipant  partParticipant; 

    @Id 
    @GeneratedValue(strategy = IDENTITY) 
    @Column(name = "CEE_ID", unique = true, nullable = false) 
    public Integer getCeeId() 
    { 
     return this.ceeId; 
    } 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "CEE_CEV_ID", nullable = false) 
    public CommonCalendarEvent getCommonCalendarEvent() 
    { 
     return this.commonCalendarEvent; 
    } 

     @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "CEE_PPT_ID", nullable = false) 
    public PartParticipant getPartParticipant() 
    { 
     return this.partParticipant; 
    } 

} 

し、最終的に:

@Entity 
@Table(name = "part_participant") 

public class PartParticipant implements java.io.Serializable 
{ 
    private static final long   serialVersionUID   = 1L; 
    private Integer      pptId; 

    @Id 
    @GeneratedValue(strategy = IDENTITY) 
    @Column(name = "PPT_ID", unique = true, nullable = false) 
    public Integer getPptId() 
    { 
     return this.pptId; 
    } 

} 

私はすべて見つけるクエリを生成するCriteriaBuilderを使用したいです特定の参加者IDのCommonCalendarEvent。私はcriteriaBuilderを書くことで、直感的な試みと思っていたもののいくつかのアプローチを試みた(私はこれHQLはどちらか正しいことを確認していないが)

"from commonCalendarEvent cce where :pptId in (cce.commonCalendarEventParts.partParticipant.pptId)" 

HQLでは、次のようになります私の試みは、 "予期せぬサブツリーの終わり"から実装エラーだけに及ぶエラーにつながっています。

..... 

    CriteriaBuilder builder = getEntityManager().getCriteriaBuilder(); 

    CriteriaQuery<CommonCalendarEvent> criteria = builder.createQuery(CommonCalendarEvent.class); 

    Root<CommonCalendarEvent> root = criteria.from(CommonCalendarEvent.class); 

    Fetch<CommonCalendarEvent, CommonCalendarEventPart> evf = root.fetch(CommonCalendarEvent_.commonCalendarEventParts, JoinType.LEFT); 

    Join<CommonCalendarEvent, CommonCalendarEventPart> evj = (Join<CommonCalendarEvent, CommonCalendarEventPart>) evf; 

    Join<CommonCalendarEventPart, PartParticipant> evpj = evj.join(CommonCalendarEventPart_.partParticipant); 
    List<Predicate> pred = new ArrayList<Predicate>(); 

    pred.add(builder.equal(evpj.get(PartParticipant_.pptId), pptId)); 
    criteria.where(builder.and(pred.toArray(new Predicate[] {}))); 
    return getEntityManager().createQuery(criteria).getResultList(); 

............. 

上記の「予期しないサブツリーの終了」エラーが発生します。

ご了承ください。

+0

投稿されたコードを確認してください: 'evf'とは何ですか? – perissf

+0

申し訳ありません修正コード。 Fetch evf ...を追加するのを忘れました。 – Mike

+0

私の更新された回答を参照してください – perissf

答えて

0

Fetch<CommonCalendarEvent, CommonCalendarEventPart> evfは不要であり、第1の結合文を修正する必要がありますクエリの

Join<CommonCalendarEvent, CommonCalendarEventPart> evj = 
          root.join(CommonCalendarEvent_.commonCalendarEventParts); 

残りは正しいようです。

+0

申し訳ありません行に入れて忘れてしまった: evf = .....しかし、それを使っても、あるいは結合してコードを実行してフェッチしなくても。私は "サブツリーの予期しない終わり"のエラーを取得します。 – Mike

+0

コードがコンパイルされていなければならないランタイム例外が発生しているので、私はそれを前提としています。 – Mike

+0

CommomCalendarEventPartデータを結果に戻すには、Fetchが必要です。だからはい、フェッチが必要です。次に、残りのデータを結合できるように結合に戻します。しかし、もし私がフェッチをしないで、代わりに参加すると、私はまだ同じエラーが発生します。ですから、CommonCalendarEventPartsのコレクションをHqlソリューションと同じ方法で扱うことができる何かが必要です。 – Mike

1

+1レイジー初期化を使用します。 JPAモデルはObjectまたはEntity指向です。したがって、これらの用語で考えるのに慣れておく必要があります。 A PartParticipantは、JPAのidによって識別されるのではなく、オブジェクト自体によって識別されます。参加者のリストがあるとします。

PartParticipant pp = em.find(PartParticipant.class, 2); 
List<PartParticipant> pps = new ArrayList<PartParticipant>(); 
pps.add(pp); 

次に、そのリストをクエリに渡します。 JPQL:

TypedQuery<CommonCalendarEvent> cev = em.createQuery("select cev from CommonCalendarEvent cev join fetch cev.commonCalendarEventParts cce where cce.partParticipant in :pps", CommonCalendarEvent.class); 
List<CommonCalendarEvent> cevs = cev.setParameter("pps", pps).getResultList(); 

LazyInitializationExceptionsを防ぐためにフェッチが必要です。 JPQLを知る

CriteriaQueryはほとんど同じに従ってください:

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<CommonCalendarEvent> q = cb.createQuery(CommonCalendarEvent.class); 
Root<CommonCalendarEvent> r = q.from(CommonCalendarEvent.class); 
Join<CommonCalendarEvent, CommonCalendarEventPart> j = r.join("commonCalendarEventParts"); 
r.fetch("commonCalendarEventParts"); 
q.select(r).where(j.get("partParticipant").in(pps)); 
List<CommonCalendarEvent> rs = em.createQuery(q).getResultList(); 

あなたはそれを実行するよりも、他のフェッチと特別な何かをする必要はありません。ご覧のとおり、クエリはPartParticipant Idを使用します。

select 
    commoncale0_.CEV_ID as CEV_ID1_0_0_, 
    commoncale1_.CEE_ID as CEE_ID1_1_1_, 
    commoncale1_.CEE_CEV_ID as CEE_CEV_2_1_1_, 
    commoncale1_.CEE_PPT_ID as CEE_PPT_3_1_1_, 
    commoncale1_.CEE_CEV_ID as CEE_CEV_2_0_0__, 
    commoncale1_.CEE_ID as CEE_ID1_1_0__ 
from cmmn_calendar_evnt commoncale0_ 
    inner join cmmn_calendar_evnt_part commoncale1_ on commoncale0_.CEV_ID=commoncale1_.CEE_CEV_ID 
where commoncale1_.CEE_PPT_ID in (?) 
+0

非常にうまく入れました。 – Mike

+0

非常にうまく入れました。私はフェッチを取って結合にキャストすることができないことを知りました。フェッチはジェネリック結合を生成するので、正当な結合は私が必要とする「SetJoin」を生成するためです。だから私の解決策は、あなたがやっていることをやって、結合とフェッチの両方をすることです。しかし、私のentityManagerでは、コードに2つの内部結合があります。しかし、1つの質問 – Mike

+0

。 PartParticipantのPPTIDとのマッチングを解決する方法は、システムがどのように知っていますか?それは "@ID"タグのためですか?私がIDを持っていないPartParticipantを渡したら、正しく動作しませんでしたか? – Mike

関連する問題