私はJPA2.0を初めて使用しますが、理解できないことがいくつかあります。
私はいくつかのテーブルを持っています:
CUST table (for customers)
--------------------------
CUST_ID (pk, integer)
CUST_NAME (varchar)
と
ORD table (for orders)
----------------------
ORD_ID (pk, integer)
ORD_STATUS (char) can be: 'N' for new, 'S' for shipped, 'D' for delivered
CUST_ID (fk, integer)
関係は単純な「1対多」です(すべての顧客が多くの注文を行うことができます)。
表の内容:
CUST_ID | CUST_NAME
-------------------
1 | elcaro
2 | tfosorcim
3 | elppa
と
ORD_ID | ORD_STATUS | CUST_ID
-----------------------------
2 | N | 1
3 | N | 1
4 | N | 1
5 | S | 1
6 | S | 1
7 | D | 1
8 | D | 1
9 | D | 1
10 | D | 2
11 | N | 2
12 | S | 3
13 | S | 3
クラスに注釈を付ける方法は次のとおりです。
@Entity(name = "Customer")
@Table(name = "CUST")
public class Customer implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "CUST_ID")
private Integer id;
@Column(name = "CUST_NAME")
private String name;
@OneToMany(mappedBy = "customer")
private List<Order> orders;
// Default constructor, getters and setters (no annotations on these)
}
と
@Entity(name = "Order")
@Table(name = "ORD")
public class Order implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "ORD_ID")
private Integer id;
@Column(name = "ORD_STATUS")
private Character status;
@ManyToOne
@JoinColumns
(
{
@JoinColumn(name = "CUST_ID", referencedColumnName = "CUST_ID")
}
)
private Customer customer;
// Default constructor, getters and setters (no annotations on these)
}
すべてが正常に機能します。次のJPQLクエリは、期待した結果をもたらします。
`select c from Customer c`
タイプCustomerの3つのオブジェクトを返します。各オブジェクトには、その顧客に属する注文が含まれています。
しかし、ここで、ステータス「N」の注文を持つ顧客のリストと、関連する注文(もちろん、ステータス「N」の注文のみ)を抽出したいと思います。古き良き時代には、次のようなSQLクエリを作成していました。
select c.cust_id,
c.cust_name,
o.ord_id,
o.ord_status
from cust c
inner join ord o on (o.cust_id = c.cust_id)
where o.ord_status = 'N'
そしてそれは次の結果セットを返したでしょう:
CUST_ID | CUST_NAME | ORD_ID | ORD_STATUS
-----------------------------------------
1 | elcaro | 2 | N
1 | elcaro | 3 | N
1 | elcaro | 4 | N
2 | tfosorcim | 11 | N
ただし、次のJPQLクエリでは、期待どおりの結果が得られません。
`select distinct c from Customer c join c.orders o where o.status = 'N'`
正しい顧客のセットを返します(顧客「elppa」にはステータス「N」の注文がなく、正しく除外されます)が、各顧客には、ステータスに関係なく、注文の完全なセットが含まれます。'where'句は、抽出する必要のある顧客のセットを決定するためにのみ評価され、その後、永続性プロバイダーが関係をナビゲートして、注文の完全なセットを抽出し始めるようです。それについて少し考えて、私はそれが理にかなっていることを認めなければなりません。
次に、別のJPQLクエリを試しました。
`select c, o from Customer c join c.orders o where o.status = 'N'`
このJPQLクエリは、前のSQLクエリによって生成された結果と同様の結果を生成します。各結果(予想どおり4つの結果)は2オブジェクト配列であり、最初のオブジェクトはタイプCustomerで、2番目のオブジェクトはタイプOrderです。ただし、ここでも、タイプCustomerのオブジェクトには、関連する注文の完全なセットが含まれています(今回は予想どおり)。注文はCustomerオブジェクトに含まれていませんが、SQL結果セットの場合と同様に、個別に返されることは言うまでもありません。
ここでの質問は次のとおりです。ステータス「N」の注文がない顧客だけでなく、ステータスが「」ではない関連注文(リレーションシップナビゲーション中に取得)を除外するJPQLクエリを作成することは可能ですか。 N'も?私が取得できるようにしたいのは、各顧客にステータス「N」の注文のみが含まれる2顧客の結果です。
Java EE 6チュートリアルを読み、例の1つ(Order Application)に私のようなスキーマがありますが、(ダウンロードしたソースコードに)このようなクエリが見つかりませんでした。
上記は標準的な動作だと思いますが、(Eclipseアダプタを介して)Oracle Weblogic 12cサーバーを使用しており、永続性プロバイダーはEclipseLinkのようです。
前もって感謝します。
よろしくお願いします、
ステファノ