He estado tratando diferentes combinaciones de HQL y Criterios y no he sido capaz de evitar algunas innecesaria une (en ambos) y algunos innecesarios selecciona (en Criteria).Cómo evitar innecesarias selecciona y se une en HQL y Criterios
En nuestro escenario, tenemos una relación@ManyToMany entre Segmento y Aplicación entidades (navegación es a partir de segmentos para Aplicaciones).
Primero probé este Criterios:
Application app = ...
List<Segment> segments = session.createCriteria(Segment.class)
.createCriteria(Segment.APPLICATIONS)
.add(Restrictions.idEq(app.getId()))
.list();
Wich produce este SQL:
select
this_.id as id1_1_,
this_.description as descript2_1_1_,
this_.name as name1_1_,
applicatio3_.segment_id as segment1_1_,
applicatio1_.id as app2_, <==== unnecessary APPLICATIONS columns
applicatio1_.id as id7_0_,
applicatio1_.name as name7_0_,
applicatio1_.accountId as accountId7_0_,
applicatio1_.applicationFlags as applicat5_7_0_,
applicatio1_.description_ as descript6_7_0_,
from
SEGMENTS this_
inner join
SEGMENTS_APPLICATIONS applicatio3_
on this_.id=applicatio3_.segment_id
inner join <==== unnecessary join
APPLICATIONS applicatio1_
on applicatio3_.app_id=applicatio1_.id
where
applicatio1_.id = ?
Como se puede ver, Criterios selecciona columnas de APLICACIONES, que no quiero para ser seleccionado No he encontrado una manera de hacerlo (¿es posible?). Además, se une con APLICACIONES, lo cual no es necesario porque el ID de la aplicación ya está en la tabla de combinación SEGMENTS_APPLICATIONS (lo mismo ocurre con HQL).
(Como una duda adicional, me gustaría saber una Restricción que utiliza la aplicación directamente, y no app.getId(). Como verá, podría hacerlo en la versión HQL de la consulta)
Como no podía limitar la parte de selección (no necesito propiedades de la aplicación) he intentado esto HQL con el "seleccionar" cláusula:
Application app = ...
List<Segment> segments = session.createQuery(
"select s from Segment s join s.applications as app where app = :app")
.setParameter("app", app)
.list();
wich produce:
select
segment0_.id as id1_,
segment0_.description as descript2_1_,
segment0_.name as name1_,
from
SEGMENTS segment0_
inner join
SEGMENTS_APPLICATIONS applicatio1_
on segment0_.id=applicatio1_.segment_id
inner join <==== unnecessary join
APPLICATIONS applicatio2_
on applicatio1_.app_id=applicatio2_.id
where
applicatio2_.id=?
Puede ver el HQL no selecciona propiedades de la aplicación (gracias a la parte "seleccionar s"), pero aún se une a la tabla APLICACIONES, lo que creo que no es necesario. ¿Cómo podemos evitar eso?
(Como nota al margen, observe que en HQL que podría utilizar aplicación directamente, y no app.getId() al igual que en los Criterios)
puede usted por favor me ayude a encontrar una manera de evitar "selecciona" en ¿Criterios y "combinaciones" innecesarias en Criteria y HQL?
(Este ejemplo es con @ManyToMany pero creo que también ocurre con @OneToMany y también con @ManyToOne y @OneToOne, incluso con fetch = LAZY).
muchas gracias, Ferran
Wow, muchas gracias. ¿Un error de larga data? No puedo creer que aún no lo hayan arreglado. ¿Solo porque hay una solución con HQL? –
No puedo creer que ya sea :-(otoh, que es software de código abierto, y que probablemente eran ocupados implementando la nueva implementación criterios JPA2, lo que probablemente se prefiere en este viejo API propietario. –
Oh, así que nos recomendarías para empezar a usar JPA2 en lugar de la antigua API de Criteria? ¿Pueden ambos mezclarse? (Solo para evitar refactorizaciones del código anterior). –