El uso de la JPA Criterios de la API, se puede hacer una captura de combinación que da como resultado sólo uno?

Usando JPA 2.0. Parece que por defecto (no explícita fetch), @OneToOne(fetch = FetchType.EAGER) campos se recuperan en 1 + N de consultas, donde N es el número de resultados que contiene una Entidad que define la relación a distintas relacionadas con la entidad. El uso de la API de Criterios, yo podría tratar de evitar que la siguiente manera:

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<MyEntity> query = builder.createQuery(MyEntity.class);
Root<MyEntity> root = query.from(MyEntity.class);
Join<MyEntity, RelatedEntity> join = root.join("relatedEntity");
root.fetch("relatedEntity");
query.select(root).where(builder.equals(join.get("id"), 3));

Lo anterior debería, idealmente, ser equivalente a la siguiente:

SELECT m FROM MyEntity m JOIN FETCH myEntity.relatedEntity r WHERE r.id = 3

Sin embargo, los criterios de resultados de la consulta en la mesa de la raíz innecesariamente se unió a la entidad relacionada con la tabla dos veces; una para la captura, y una vez para el donde el predicado. El SQL resultante se ve algo como esto:

SELECT myentity.id, myentity.attribute, relatedentity2.id, relatedentity2.attribute 
FROM my_entity myentity 
INNER JOIN related_entity relatedentity1 ON myentity.related_id = relatedentity1.id 
INNER JOIN related_entity relatedentity2 ON myentity.related_id = relatedentity2.id 
WHERE relatedentity1.id = 3

Ay, si yo sólo hago la captura, entonces no tengo una expresión a utilizar en la cláusula where.

Que me estoy perdiendo algo, o es esta una de las limitaciones de la API de Criterios? Si es esto último, es este ser subsanado en JPA 2.1 o hay alguna específica del proveedor de mejoras?

De lo contrario, parece mejor para dar justo arriba de tipo en tiempo de compilación comprobación (me doy cuenta de que mi ejemplo no usar el metamodelo) y el uso dinámico de JPQL TypedQueries.

InformationsquelleAutor Shaun | 2013-06-25

3 Kommentare

  1. 26

    Lugar de root.join(...) puede utilizar root.fetch(...) que devuelve Fetch<> objeto.

    Fetch<> es descendiente de Join<> pero puede ser utilizado de manera similar.

    Usted sólo necesita para lanzar Fetch<> a Join<> se debe trabajar para EclipseLink y de Hibernación

    ...
    Join<MyEntity, RelatedEntity> join = (Join<MyEntity, RelatedEntity>)root.fetch("relatedEntity");
    ...
    • Fetch es ni una subinterface de Unirse, ni Expresión, así que no se puede asignar a una combinación y no los puedo usar en una cláusula where (por ejemplo). Referencia: docs.oracle.com/javaee/6/api/javax/persistence/criteria/…, por Lo tanto, ¿cómo es esto posible? Es específica del proveedor?
    • Lo siento, usted debe lanzarla. Se debe trabajar por lo menos para Hybernate como se describe aquí, docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/… he solucionado mi respuesta.
    • Esto funcionó para mí, pero la conversión a un Join<MyEntity, RelatedEntity> causa de mi IDE a de la bandera de la instrucción como una advertencia. He encontrado que la fundición a la org.hibernate.ejb.criteria.path.SingularAttributeJoin<MyEntity, RelatedEntity> hizo la advertencia desaparece. Llamar root.fetch hace lo siguiente: FetchParent#fetch(String) AbstractFromImpl#fetch(String) [Implementation of FetchParent] AbstractFromImpl#fetch(SingularAttribute, JoinType) AbstractFromImpl#constructJoin(SingularAttribute,JoinType) [Returns SingularAttributeJoin]
    • Funciona, gracias, pero la más puedo usar JPA Criterios más me parece detallado & no es intuitivo.
    • Lo que usted puede probar querydsl.com
    • Bozek GUARDAR MI DÍA ! MUCHAS GRACIAS!!!!!!!!!!!!!!!!
    • Tipo de viejo tema, pero tal vez usted va a saber: incluso tho es posible lanzar de Fetch a Join usted no puede hacer fetch.on(...), porque va a decir que with clause cannot be used with fetch join - use filters. Tengo que añadir una condición adicional para la combinación (además de la ID). Cuando acabo de hacer root.join(...) y, a continuación, join.on(...) combinaciones correctas se generan, pero no son la captura que se unió a los datos (no de los campos enumerados en los selecciona). Tal vez usted conoce alguna solución?
    • Esto realmente funciona. Pero, ¿es una mejor solución? Es a mí me parece que es simplemente algún tipo de solución? Join interfaz no es un subtipo de Fetch. Su interfaz común es FetchParent. Tiene más estrecho ámbito de aplicación de los métodos. Yo realmente no llegar a donde es que oculta la implementación encuentra? Pero para este ejemplo join.get() obras.
    • Convertir a (Join) para hacer su IDE feliz!

  2. 5

    Comenzando con JPA 2.1 usted puede utilizar entidad dinámica gráficos para esto. Retire su captura y especificar una entidad como el gráfico de la siguiente manera:

    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<MyEntity> query = builder.createQuery(MyEntity.class);
    Root<MyEntity> root = query.from(MyEntity.class);
    Join<MyEntity, RelatedEntity> join = root.join("relatedEntity");
    query.select(root).where(builder.equal(join.get("id"), 3));
    EntityGraph<MyEntity> fetchGraph = entityManager.createEntityGraph(MyEntity.class);
    fetchGraph.addSubgraph("relatedEntity");
    entityManager.createQuery(query).setHint("javax.persistence.loadgraph", fetchGraph);
    • El método correcto de CriteriaBuilder es igual no es igual
  3. 1

    Utilizando root.fetch() en EclipseLink creará un SQL con INNER JOIN porque tienen 3 tipos y el valor predeterminado es la INTERIOR.

    INNER,  LEFT,  RIGHT;

    La sugerencia es usar CreateQuery.

    TypedQuery<T> typedQuery = entityManager.createQuery(query);

    EDIT: puedes lanzar la raíz De como esta:

    From<?, ?> join = (From<?, ?>) root.fetch("relatedEntity");
    • La pregunta es acerca de CriteriaQuery no tiene setHint
    • Me explicó cómo ayuda el uso de otro método para resolver. Si usted no entiende que yo no puedo hacer nada.
    • Cuando se utiliza la API de criterios para crear una consulta que usted no tirar todo su código, para en su lugar construir una consulta con TypedQuery por lo que puede establecer una sugerencia Consulte «Uso de la JPA API de Criterios» en el título de la pregunta. Así podría sugerir cómo hacerlo con sql
    • Que puedo hacer entityManager.createQuery(CriteriaQuery) como esta!!! Usted puede utilizar: String, CriteriaQuery, CriteriaUpdate y CriteriaDelete.
    • Leer esta API docs.oracle.com/javaee/6/api/javax/persistence/criteria/… usted ve a un setHint?
    • Leer esto. docs.oracle.com/cd/E19226-01/820-7627/gjitv/index.html. Aquí tienes una Consulta, que utiliza setHint. docs.oracle.com/javaee/6/api/javax/persistence/Query.html
    • Esta pregunta no es acerca de la interfaz de Consulta. Es acerca de CriteriaQuery que no implemente dicha interfaz. Así podría sugerir algunos SQL. Por favor, lea la pregunta y mi comentario de nuevo
    • El hombre, que es una SUGERENCIA. Voy a quitar lo aceptar?
    • 1000 puntos! Muchas gracias! Solucionado mi problema después de un día de trabajo!

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea