Consulta de JPQL: ¿cómo filtrar filas en una relación?

Soy nuevo en JPA 2.0 y hay algunas cosas que no entiendo.

Tengo un par de mesas:

<code>

    CUST table (for customers)
    --------------------------
    CUST_ID   (pk, integer)
    CUST_NAME (varchar)

</code>

y

<code>

    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)

</code>

La relación es un simple "uno a muchos" (cada cliente puede realizar muchos pedidos).

Contenido de las tablas:

<code>

    CUST_ID | CUST_NAME
    -------------------
     1      | elcaro
     2      | tfosorcim
     3      | elppa

</code>

y

<code>

    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

</code>

Así es como anoté mis clases:

<code>

    @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)
    }

</code>

y

<code>

    @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)
    }

</code>

Todo funciona bien, la siguiente consulta de JPQL arroja los resultados que esperaba:

<code>`select c from Customer c`</code>

devuelve tres objetos de tipo Cliente, cada uno de los cuales contiene los pedidos que pertenecen a ese cliente.

Pero ahora, quiero extraer la lista de clientes que tienen pedidos en estado 'N', junto con los pedidos asociados (solo los pedidos de estado 'N', por supuesto). En los buenos tiempos, habría escrito una consulta SQL como esta:

<code>

    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'

</code>

y habría devuelto el siguiente conjunto de resultados:

<code>

    CUST_ID | CUST_NAME | ORD_ID | ORD_STATUS
    -----------------------------------------
     1      | elcaro    | 2      | N
     1      | elcaro    | 3      | N
     1      | elcaro    | 4      | N
     2      | tfosorcim | 11     | N

</code>

La siguiente consulta de JPQL, sin embargo, no produce los resultados esperados:

<code>`select distinct c from Customer c join c.orders o where o.status = 'N'`</code>

devuelve el conjunto correcto de clientes (el cliente 'elppa' no tiene ningún pedido de estado "N" y se excluye correctamente), pero cada cliente contiene el conjunto completo de pedidos, independientemente del estado. Parece que la cláusula 'donde' solo se evalúa para determinar qué conjunto de clientes se debe extraer y luego el proveedor de persistencia comienza a navegar la relación para extraer el conjunto completo de pedidos. Pensando un poco en ello, debo admitir que tiene sentido.

Luego probé otra consulta de JPQL:

<code>`select c, o from Customer c join c.orders o where o.status = 'N'`</code>

esta consulta JPQL produce resultados similares a los producidos por la consulta SQL anterior: cada resultado (4 resultados como se esperaba) es una matriz de 2 objetos, el primer objeto es de tipo Cliente y el segundo objeto es de tipo Orden. Pero, nuevamente, los objetos de tipo Cliente contienen el conjunto completo de pedidos relacionados (como esperaba, esta vez). Sin mencionar el hecho de que ahora los pedidos no están contenidos en los objetos del Cliente, sino que se devuelven por separado, como en un conjunto de resultados SQL.

Ahora la pregunta es: ¿es posible escribir una consulta de JPQL que filtre, no solo a los clientes que no tienen un pedido en estado 'N', sino a los pedidos relacionados (obtenidos durante la navegación de la relación) que no están en estado? N 'también? Lo que me gustaría poder obtener es un resultado de 2 clientes donde cada cliente contiene solo sus pedidos de estado "N".

Leí el Tutorial de Java EE 6 y uno de los ejemplos (la Solicitud de pedido) tiene un esquema similar al mío, pero no pude encontrar una consulta como esta (en el código fuente descargado).

Aunque creo que lo anterior es un comportamiento estándar, uso un servidor Oracle Weblogic 12c (a través de su adaptador Eclipse) y el proveedor de persistencia parece ser EclipseLink.

Gracias por adelantado.

Atentamente,

Stefano

Respuestas a la pregunta(1)

Su respuesta a la pregunta