2012-05-19 20 views
5

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

Respuesta

5

Las columnas adicionales seleccionadas al usar Criteria provienen de un antiguo bug in Hibernate. AFAIK, la única forma de evitarlo es usar HQL, o la API de criterios JPA2.

El otro problema también se señala como a bug, pero tiene menos impactos, y no me importaría demasiado.

+0

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? –

+0

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. –

+0

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). –

-2

¿Cuál es la pregunta? Si se trata de cómo forzar la unión de NO pasando luego ver este artículo en precompilar LINQ http://msdn.microsoft.com/en-us/magazine/ee336024.aspx

y Compiled LINQ joins

De lo contrario se limite a escribir la consulta a sí mismo y, obviamente, la unión no estaría allí ....

+0

La pregunta es cómo evitar la selección de aplicaciones en Criterios y la aplicación se unen en Criteria y HQL. Estamos usando Hibernate. –

+0

Sí, viene con Visual Studio. Debería tener construcciones similares. – Jay

+0

(Eliminé el "Es LINQ otro ORM" pero ahora no puedo devolverlo) –

Cuestiones relacionadas