Foros del Web » Programación para mayores de 30 ;) » Java »

[SOLUCIONADO] Join Criteria JPA

Estas en el tema de Join Criteria JPA en el foro de Java en Foros del Web. Tengo una tabla Aplicacion y una Tabla GrupoAplicacion. Hago una busqueda de aplicaciones @import url("http://static.forosdelweb.com/clientscript/vbulletin_css/geshi.css"); Código Java: Ver original public Predicate toPredicate ( Root < ...
  #1 (permalink)  
Antiguo 20/11/2014, 10:41
 
Fecha de Ingreso: octubre-2008
Ubicación: Madrid
Mensajes: 352
Antigüedad: 16 años
Puntos: 5
Join Criteria JPA

Tengo una tabla Aplicacion y una Tabla GrupoAplicacion.
Hago una busqueda de aplicaciones
Código Java:
Ver original
  1. public Predicate toPredicate(Root<Aplicacion> aplicacion, CriteriaQuery<?> query, CriteriaBuilder cb) {
  2. ....

Quiero cargar dos listados de aplicaciones pero filtrados,
1-que en uno salga todos las aplicaciones menos las del grupo que le envío,
2- y en el otro al revés.

Código Java:
Ver original
  1. if (grupoAplicacion != null && !grupoAplicacion.isNewObject()) {
  2.       Root<GrupoAplicacion> grupoAplicacion = query.from(GrupoAplicacion.class);
  3.       Join<GrupoAplicacion, Aplicacion> aplicacionesJoin = grupoAplicacion.join(GrupoAplicacion_.aplicaciones);
  4.  
  5.       if (asociadas) { // boolean
  6.         restrictionsList.add(cb.and(cb.in(aplicacion).value(aplicacionesJoin))); // carga las del join
  7.       } else {
  8.         restrictionsList.add(cb.not(cb.in(aplicacion).value(aplicacionesJoin))); // carga todas menos la del join
  9.       }
  10.  
  11.     }

El primer caso no me sale bien, ya que salen las aplicaciones repetidas.
No se si la sintaxis esta bien, necesito que en "aplicacionJoin" me cargue la aplicaciones del grupo en cuestión.
Para que si le paso asociadas = true me carge todas menos las del grupo.
y si le paso asociadas = false, me carge las del propio grupo.
  #2 (permalink)  
Antiguo 21/11/2014, 00:14
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 9 meses
Puntos: 260
Sonrisa Respuesta: Join Criteria JPA

Hola,

Posiblemente yo no comprendí bien, pero al mismo tiempo posiblemente te sea de alguna ayuda,

Cita:
Iniciado por jlgarcia1977 Ver Mensaje
... 1-que en uno salga todos las aplicaciones menos las del grupo que le envío,...
¿En donde se lo estás enviando?
¿Cómo sabe la consulta que grupo le estás enviando?

Mientras no haya una clausula where específicamente de un grupo entonces son todos contra todos. Hasta ese momento no estas trabajando con data, estas construyendo un query. Y en el código que pusiste yo no veo ningún discriminador de un grupo específico.

Cita:
Iniciado por jlgarcia1977 Ver Mensaje
...El primer caso no me sale bien, ya que salen las aplicaciones repetidas. ...
En el primer caso posiblemente salen repetidas porque existe un producto cartesiano, el join junta las dos tablas pero no le estas indicando cual grupo quieres usar, posiblemente si le das vuelta al join y le quitas el segundo root que create con query.from() funcione mejor. En el segundo caso, no sabría porque funciona, posiblemente por la data con la que estas probando.

Cita:
Iniciado por jlgarcia1977 Ver Mensaje
... No se si la sintaxis esta bien, necesito que en "aplicacionJoin" me cargue la aplicaciones del grupo en cuestión. ...
¿El grupo en cuestión cual es?

Mientras no le digas, este grupo "1" es el grupo en cuestión va a hacer un join de toda la tabla con toda la otra tabla, a menos que haya algo adicional que no mostraste, que diga el grupo en cuestión es "1", en ese caso hubiera sido muy útil que lo hubieras mostrado.

Saludos,
  #3 (permalink)  
Antiguo 21/11/2014, 01:50
 
Fecha de Ingreso: octubre-2008
Ubicación: Madrid
Mensajes: 352
Antigüedad: 16 años
Puntos: 5
Respuesta: Join Criteria JPA

Si me he dado cuenta...

Código Java:
Ver original
  1. if (grupoAplicacion != null && !grupoAplicacion.isNewObject()) { <--grupoAplicacion que envió
  2.       Root<GrupoAplicacion> grupoAplicacionRot = query.from(GrupoAplicacion.class);
  3.       Join<GrupoAplicacion, Aplicacion> aplicacionesJoin = grupoAplicacionRoot.join(GrupoAplicacion_.aplicaciones);
  4. // AQUI ME FALTA DECIR QUE EL grupoAplicacionRoot sea el grupoAplicacion que envió, pero //no se la sintaxis
  5.  
  6.       if (asociadas) { // boolean
  7.         restrictionsList.add(cb.and(cb.in(aplicacion).value(aplicacionesJoin))); // carga las del join
  8.       } else {
  9.         restrictionsList.add(cb.not(cb.in(aplicacion).value(aplicacionesJoin))); // carga todas menos la del join
  10.       }
  11.  
  12.     }
  #4 (permalink)  
Antiguo 21/11/2014, 13:21
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 9 meses
Puntos: 260
Sonrisa Respuesta: Join Criteria JPA

Hola,

Posiblemente todavía sigo sin entender, pero como dije anteriormente posiblemente te sea de alguna ayuda,

Cita:
Iniciado por jlgarcia1977 Ver Mensaje
Si me he dado cuenta...
Código Java:
Ver original
  1. if (grupoAplicacion != null && !grupoAplicacion.isNewObject()) { <--grupoAplicacion que envió
  2.       Root<GrupoAplicacion> grupoAplicacionRot = query.from(GrupoAplicacion.class);....
Me confundió bastante el hecho que al parecer tu Entity grupoAplicacion, (que todavía no estoy seguro que sea un Entity, porque no se mira la definición), se ocultaba por la variable de tipo Root grupoAplicacion. Es decir, se llaman igual pero tiene diferente ámbito.

Para mi, es bastante confuso el concepto de lo que quieres hacer, aunque la idea que yo entendí parece simple según el enunciado. Yo no comprendo bien que es lo que necesitas saber, porque pareciera que no estas resolviendo el problema adecuadamente, pareciera que estas metiendo conceptos innecesarios pero al mismo tiempo pareciera que conoces bien de bases de datos y JPA.

Yo, en mi caso personal lo resolvería (lo que yo entendí) de la siguiente forma.

Tengo dos tablas Aplicaciones y GrupoAplicaciones, relacionadas, por uno o mas campos, y tengo una entidad GrupoAplicacionesEntity de la tabla GrupoAplicaciones, quiero todos los registros de Aplicaciones que sean iguales en la relación con GrupoAplicacionesEntity, y aparte quiero otra consulta de todos los registros de Aplicaciones que no sean iguales en la relación.

Entonces, ¿para que necesito la relación? si ya tengo toda la información necesaria para extraer las Aplicaciones que cumplan con GrupoAplicacionesEntity. Aplicaciones seguramente ya tiene los campos que relacionan con GrupoAplicaciones, solamente le pondría que sean iguales a GrupoAplicacionesEntity.

Por ejemplo, (algo así, yo uso un predicate para unir todo el where y se lo aplico al final, posiblemente tendrás que cambiar algunas o muchas cosas para que sea adapte a tu List<>):
Código Java:
Ver original
  1. Path<Integer> grupoID = root.get(Aplicaciones_.grupoId);
  2. predicate = cb.and(predicate, cb.equal(grupoID, GrupoAplicacionesEntity.id));
Si miras el SQL con un logger FINE (quedaría algo así):
Código SQL:
Ver original
  1. SELECT .. FROM Aplicaciones
  2. WHERE Aplicaciones.grupoID = 8
Esa consulta me devolvería todos los registros en Aplicaciones que tengan el mismo GrupoAplicaciones. Y en el otro caso usas cb.not(), te devolvería todo, menos el GrupoAplicaciones que le enviaste. Por eso yo no miro la necesidad del .join(), a menos que haya algo adicional como un LEFT JOIN, que es diferente. U otros motivos, que no sea un Entity, que no venga la información completa, que busques por un campo diferente que el grupoId, y un largo etc.

En ese caso posiblemente si necesites el .join(), pero aún así no miro la necesidad de crear otro Root. Solamente el .join() es necesario, y adicionalmente seleccionar el GrupoID con el .equals(), posiblemente con otro u otros campos del .join().

En base a lo que entendí es todo lo que puedo decir, sino posiblemente alguien mas que haya comprendido mejor podría ayudarte,

Saludos,

Última edición por HackmanC; 21/11/2014 a las 13:34 Razón: agregar otros motivos
  #5 (permalink)  
Antiguo 22/11/2014, 13:51
 
Fecha de Ingreso: octubre-2008
Ubicación: Madrid
Mensajes: 352
Antigüedad: 16 años
Puntos: 5
Respuesta: Join Criteria JPA

Está era la solución. No estaba haciendo bien la subquery.

Código Java:
Ver original
  1. Subquery<Aplicacion> subqueryGrupo = query.subquery(Aplicacion.class);
  2.       Root<GrupoAplicacion> filtroGrupo = subqueryGrupo.from(GrupoAplicacion.class);
  3.       Join<GrupoAplicacion, Aplicacion> aplicacionesJoin = filtroGrupo.join(GrupoAplicacion_.aplicaciones);
  4.  
  5.       subqueryGrupo.select(aplicacionesJoin);
  6.       subqueryGrupo.where(cb.equal(filtroGrupo, grupoAplicacion));
  7.  
  8.       if (asociadas) {
  9.         restrictionsList.add(cb.and(cb.in(aplicacion).value(subqueryGrupo)));
  10.       } else {
  11.         restrictionsList.add(cb.not(cb.in(aplicacion).value(subqueryGrupo)));
  12.       }
  #6 (permalink)  
Antiguo 22/11/2014, 20:43
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 9 meses
Puntos: 260
Sonrisa Respuesta: Join Criteria JPA

Hola,

Cita:
Iniciado por jlgarcia1977 Ver Mensaje
Está era la solución. No estaba haciendo bien la subquery.
Pues que te diré. No tengo ni idea de la estructura de las tablas, ni creo haberte entendido completamente todavía. Pero si me permites darte el mismo consejo de nuevo, posiblemente te sea de alguna ayuda.

Básicamente estas haciendo usando la cláusula JOIN con un IN en un subquery, para algo que posiblemente no necesitas, tienes 2 tablas y en una tabla tienes toda la información necesaria para saber si cumplen o no.

En SQL podrías verlo de la siguiente forma:

Código SQL:
Ver original
  1. SELECT ... FROM app a, grupo b
  2. WHERE a.grupo IN (SELECT ... FROM grupo WHERE a.algo = b.algo)

Cuando podrías hacer lo mismo simplemente:

Código SQL:
Ver original
  1. SELECT .. FROM app a WHERE a.grupo = algo

Pero si a ti te funciona, no creo que haya que darle mas vueltas al asunto, y terminado el asunto por mi parte, posiblemente hay algo o mucho que no haya entendido yo todavía. Lo interesante es que aún los que entienden JPA y Spring Data normalmente no van a notar la diferencia.

Saludos,
  #7 (permalink)  
Antiguo 24/11/2014, 03:13
 
Fecha de Ingreso: octubre-2008
Ubicación: Madrid
Mensajes: 352
Antigüedad: 16 años
Puntos: 5
Respuesta: Join Criteria JPA

La Specificacion es sobre la tabla Aplicaciones y busco aplicaciones.
Pero hay una casuística que es cuando busco aplicaciones para un grupo de aplicaciones.
Entonces en ese caso y solo en ese caso, entra en juego la tabla GrupoAplicaciones, para que si le mando el grupo que estoy editando, me traiga todas las aplicaciones menos la que ya tenga ese grupo. y es donde necesito el código de arriba.
Espero haber sido más claro.
De todos modos muchísimas gracias por tu interés.
Un saludo.

Etiquetas: criteria, join, jpa
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 00:57.