Quiero hacer una consulta donde puedo unir 2 tablas, utilizando el CriteriaBuilder. En MySQL la consulta yo estoy tratando de hacer que tendría este aspecto:

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

Quiero llegar a todos los pedidos y si tienen un elemento de tipo #1, quiero unirme con este elemento. Sin embargo, si no hay ningún elemento de tipo #1 se encuentra, todavía quiero conseguir el pedido. Yo no puedo averiguar cómo hacer esto con el CriteriaBuilder. Todo lo que sé hacer es:

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));

Esta consulta se rompió, ya que resulta en algo como esto en MySQL:

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

El resultado sólo contienen órdenes con elementos de tipo #1. Órdenes sin son excluidos. ¿Cómo puedo utilizar el CriteriaBuilder para crear una consulta como en el primer ejemplo?

quiero recibir todos los pedidos y si tienen un elemento de tipo #1, este elemento debe ser incluido en el resultado es ¿Qué tipo de resultados quieres? Pedido? O una tupla / multiselect? ¿Qué quieres más de todos los pedidos? Por favor explique
Lo siento, yo no estaba muy claro. He corregido la descripción. No estoy realmente interesado en obtener el elemento como parte de mi resultado. Sólo quiero órdenes en mi resultado. Básicamente, quiero ordenar el resultado en base a los elementos de un tipo específico, mientras sigue recibiendo órdenes sin que tipo de elementos.
Es posible con CriteriaBuilder ! Mira mi respuesta abajo

OriginalEl autor Bjørn Stenfeldt | 2013-04-13

5 Comentarios

  1. 11

    Es posible hacer que el uso de la on método Join<Z, X> on(Predicate... restrictions);.

    Aquí está un ejemplo:

    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));
    Si esto funciona, que serán muy pocas las consultas nativas que pueden ser reemplazados. Me probarlo la próxima vez que necesite una combinación.
    Yo no se lo que quieres decir con «pocas las consultas nativas que pueden ser sustituidos» ! Pruebe primero y verás que funciona perfectamente !
    Yo simplemente quería decir que tengo un montón de lugares donde los puedo usar entityManager.createNativeQuery(String) debido a las deficiencias de la CriteriaBuilder. 🙂
    me ayudan por favor a construir consulta similar. Echa un vistazo a esta pregunta por favor stackoverflow.com/questions/46793743/…

    OriginalEl autor hzitoun

  2. 1

    Creo que este es el mismo problema que se plantea en esta pregunta. Parece que no es posible en CriteriaBuilder. Es posible en modo de Hibernación Criterios de la API, pero que probablemente no va a ayudar.

    JPA Criterios de API: condición Múltiples en LEFT JOIN

    La primera MySQL es lo que quiero que mi CriteriaBuilder a generar. La segunda MySQL representa lo que la muestra CriteriaQuery genera. Si yo simplemente agregar or item.id is null a la segunda consulta de MySQL, no estoy consiguiendo lo que quiero. Haciendo que excluiría a los pedidos con los elementos que tienen un type_id diferentes de 1, y sólo órdenes de restitución con elementos de tipo 1 o ninguna en lo absoluto.
    Tengo ahora Bjørn. Estoy editando mi respuesta.
    Gracias. Yo podría darle una oportunidad en una escala más pequeña, pero en mi actual proyecto probablemente no me ayuda. Ahora mismo estoy en EclipseLink (JPA 2.0). Como he sido capaz de encontrar (enlace), la característica necesito no estarán disponibles hasta JPA 2.1. Espero que pronto.
    Es posible con CriteriaBuilder ! Mira mi respuesta por el tuyo

    OriginalEl autor carbontax

  3. 0

    Sé que esta pregunta fue hecha hace mucho tiempo, pero recientemente tuve el mismo problema y he encontrado esta solución de Oracle foro, he copiado y pegado en caso de que el enlace no se encuentra disponible.

    MiguelChillitupaArmijos 29-abr-2011 1:41 (en respuesta a un 840578) Creo
    usted debe usar algo como:

    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(); 

    Una, este es el link.

    JPA Criterios : LEFT JOIN con una condición

    OriginalEl autor OJVM

  4. 0

    SOBRE la cláusula es compatible en modo de Hibernación 4.3 versión, nadie es consciente de que si no hay un parámetro de indexación problema entre el índice de parámetros de la medida adicional de condiciones con el índice de la asignación existente filtros al hacer una combinación externa EN la cláusula?

    El uso de la Persona de clase de entidad a continuación como ejemplo, decir que estoy añadiendo este filtro para limitar los tipos de dirección y el filtro está habilitado para rellenar la cláusula IN. El índice de parámetros de la cláusula será causa el problema [2] al añadir condiciones adicionales (tales como el uso de «calle» de la columna) parte de la cláusula. Se trata de un problema conocido?

    [1] @Filtro(name = «addressTypes», condición = «ADDRESS_TYPE en (:supportedTypes)»)

    [2]
    Causado por: ERROR 22018: carácter no Válido de cadena de formato para el tipo BIGINT.
    privado Conjunto de direcciones;

    OriginalEl autor user3390708

  5. -1

    Hay una solución si usted está usando Hibernate 3.6 con JPA 2.0
    No es la mejor solución, sin embargo, funciona perfecto para mí.

    He duplicado la entidad con el @Donde hibernate anotación.Esto significa que cada vez que uso la combinación con esta entidad, hibernate añadir la condición en la instrucción join en SQL generado.

    Por ejemplo, inicialmente tenemos el siguiente ejemplo:

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

    Con el fin de añadir condiciones adicionales en los criterios de combinación, necesitamos duplicar la Dirección @Entidad de asignación , la adición de la @, Donde la anotación @Donde(cláusula = «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;
    
    }

    También, tenemos que añadir la duplicación de la asignación de la asociación para la nueva entidad.

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

    Por último, puede utilizar una combinación con esta Entidad específica en sus criterios :

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

    La Hibernación Fragmento de código SQL deben parece que esto :

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

    OriginalEl autor Eduardo Fabricio

Dejar respuesta

Please enter your comment!
Please enter your name here