2013-04-13 6 views
13

CriteriaBuilderを使用して2つのテーブルを結合するクエリを作成します。 MySQLでは、私が作るしようとしているクエリは次のようになります。カスタム "オン"条件でCriteriaBuilderを結合する方法は?

SELECT * FROM order 
LEFT JOIN item 
ON order.id = item.order_id 
AND item.type_id = 1 

私はすべての注文を取得したいと、彼らはタイプ#1のアイテムを持っている場合、私はこの項目に参加したいです。しかし、タイプ#1のアイテムが見つからない場合は、依然として注文を取得したいと考えています。私はCriteriaBuilderでこれを作る方法を理解できません。

SELECT * FROM order 
LEFT JOIN item 
ON order.id = item.order_id 
WHERE item.type_id = 1 

結果は唯一のタイプの#1のアイテムとの注文が含まれます:私が作る方法を知っているすべてがある:それは、MySQLでこのようなものになり以来

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<Order> cq = cb.createQuery(Order.class); 
Root<Order> order = cq.from(Order.class); 
Join<Order, Item> item = order.join(Order_.itemList, JoinType.LEFT); 
Join<Item, Type> type = order.join(Item_.type, JoinType.LEFT); 
cq.select(order); 
cq.where(cb.equal(type.get(Type_.id), 1)); 

このクエリは、破産です。なしの注文は除外されます。最初の例のようにCriteriaBuilderを使用してクエリを作成するにはどうすればよいですか?

+0

_すべての注文を受け取り、#1のタイプのアイテムがある場合は、このアイテムをresult_に含める必要があります。どのような結果タイプが必要ですか?注文?またはタプル/マルチセレクション?あなたはすべての注文よりも何を望んでいますか?説明してください – perissf

+0

申し訳ありませんが、私は非常に明確ではなかった。私は説明を修正しました。私は実際に私の結果の一部としてアイテムを取得することに興味がありません。私はただ私の結果で注文したい。基本的には、特定のタイプのアイテムに基づいて結果を並べ替えると同時に、そのタイプのアイテムがなくても注文を受けたいのです。 –

+0

CriteriaBuilderで可能です!私の答えはぼんやりしています – Mitchapp

答えて

1

私はこれがこの問題と同じ問題だと思います。 CriteriaBuilderでは不可能なようです。 Hibernate Criteria APIで可能ですが、おそらくあなたを助けません。

JPA Criteria API: Multiple condition on LEFT JOIN

+0

最初のMySQLは私のCriteriaBuilderが生成したいものです。 2番目のMySQLは、表示されたCriteriaQueryが生成するものを表します。 2番目のMySQLクエリに 'またはitem.id is null'を単に追加すると、私は自分が望むものを得ることができません。そうすることで、type_idが1以外のアイテムの注文は除外され、タイプ1のアイテムの注文のみ、またはアイテムのないアイテムのみが返されます。 –

+0

私は今それを得るBjørn。私は自分の答えを編集しています。 – carbontax

+0

ありがとうございます。私はそれを小さな規模で試みるかもしれませんが、私の現在のプロジェクトではおそらく私を助けません。今はEclipseLink(JPA 2.0)を利用しています。私が見つけた限りでは([リンク](https://blogs.oracle.com/arungupta/entry/jpa_2_1_early_draft))、私が必要とする機能はJPA 2.1まで利用できません。うまくいけばそれはすぐになります。 –

0

私は念のためにリンクが長くない私はコピーして貼り付け、この質問は同じ問題を抱えていたと私はOracleのフォーラムから、この解決策を見つけ、最近、長い時間行かせたしたが、知っています利用可能です。これはリンクである

em.createQuery("SELECT DISTINCT e.Id" + 
        " from Email e " + 
        " left join e.idEmailIn e2 *with* e2.responseType = 'response'" + 
        "  where e.type = 'in' and e.responseMandatory = true").getSingleResult(); 

アン:

MiguelChillitupaArmijos 29-ABR-2011 1時41分(エンrespuesta 840578)は、あなたがのようなものを使用する必要があり 考えます。

JPA Criteria : LEFT JOIN with an AND condition

-1

あなたはJPA 2.0 を使ったHibernate 3.6を使用している場合、回避策はありしかし、それは私のために完璧に動作し、よりよい解決策ではありません。

私はエンティティと@Where hibernateアノテーションを複製しています。これは、このエンティティとの結合を使用するたびに、生成されたSQLで結合ステートメントに余分な条件が追加されることを意味します。例えば

、最初に我々は例従っています基準に余分な条件を追加するために

@Entity 
@Table(name = "PERSON") 
public class Person { 

    @Id 
    @Column(name = "PERSON_ID") 
    private Long id; 

    @Id 
    @Column(name = "PERSON_NAME") 
    private String name; 

    @OneToMany(mappedBy = "person", fetch = FetchType.LAZY) 
    private Set<Address> addresses; 

} 

@Entity 
@Table(name = "ADDRESS") 
public class Address { 

    @Id 
    @Column(name = "ADDRESS_ID") 
    private Long id; 

    @Id 
    @Column(name = "ADDRESS_STREET") 
    private String street; 

    @ManyToOne 
    @JoinColumn(name = "PERSON_ID") 
    private Person person; 

} 

参加、我々は@Where注釈@Where(句を=追加、アドレス@Entityマッピングを複製する必要があります"ADDRESS_TYPE_ID = 2")。

@Entity 
@Table(name = "ADDRESS") 
@Where(clause = " ADDRESS_TYPE_ID = 2") 
public class ShippingAddress { 

    @Id 
    @Column(name = "ADDRESS_ID") 
    private Long id; 

    @Id 
    @Column(name = "ADDRESS_STREET") 
    private String street; 

    @OneToOne 
    @JoinColumn(name = "PERSON_ID") 
    private Person person; 

} 

また、新しいエンティティに重複マッピングの関連付けを追加する必要があります。

@Entity 
@Table(name = "PERSON") 
public class Person { 

    @Id 
    @Column(name = "PERSON_ID") 
    private Long id; 

    @Id 
    @Column(name = "PERSON_NAME") 
    private String name; 

    @OneToMany(mappedBy = "person", fetch = FetchType.LAZY) 
    private Set<Address> addresses; 

    @OneToOne(mappedBy = "person") 
    private ShippingAddress shippingAddress; 

} 

最後に、あなたはあなたの基準では、この特定のエンティティとの結合を使用することができます

PersonRoot.join(Person_.shippingAddress, JoinType.LEFT); 

休止スニペットSQLをすべきである。このように思える:

left outer join 
     address shippingadd13_ 
      on person11_.person_id=shippingadd13_.person_id 
      and (
       shippingadd13_.ADDRESS_TYPE_ID = 2 
      ) 
4

あなたはCAN行いますそれはonメソッドJoin<Z, X> on(Predicate... restrictions);を使用しています。ここで

は実施例である:句ON

... 
Root<Order> order = cq.from(Order.class); 
Join<Order, Item> item = order.join(Order_.itemList, JoinType.LEFT); 
item.on(cb.equal(item.get(Item_.type), 1)); 
... 
+0

これがうまくいくと、かなりのネイティブクエリが置き換えられることになります。私は次回は参加を必要とします。 –

+0

「置き換えることのできるネイティブクエリはほとんどありません」という意味はありませんでした。 まず試してみてください。それが完璧に動作することがわかります! – Mitchapp

+0

私は、CriteriaBuilderの欠点のために、 'entityManager.createNativeQuery(String)'を使用する場所がたくさんあることを意味しました。 :-) –

0

にHibernate 4.3のバージョンでサポートされているのインデックスを持つ、追加のカスタム条件のパラメータインデックス間のパラメータのインデックス作成の問題がある場合は、誰もが認識していますON句で外部結合を実行するときの既存のマッピングフィルタ?

以下のPersonエンティティクラスを例として使用して、このフィルタを追加してアドレスタイプを制限し、IN句にフィルタを設定できるようにします。 IN句のパラメータインデックスは、ON句の 'street'カラムのような追加条件を追加するときに問題[2]を引き起こします。それは既知の問題ですか?

[1] @Filter(名= "addressTypes"、状態= "(中ADDRESS_TYPE:supportedTypes)")

[2] に起因:タイプBIGINTの無効な文字列の形式:ERROR 22018。 プライベートセットアドレス。

関連する問題