2011-07-06 12 views
5

que tienen un 'padre' entidad que tiene un conjunto de enumeracionesla comparación de dos colecciones de enumeraciones con Hibernate o SQL

private Set<MyEnum> myEnums = EnumSet.noneOf(MyEnum.class); 

    @CollectionOfElements(targetElement=MyEnum.class) 
    @JoinTable 
     (name="PARENT_MY_ENUM", 
     [email protected](name="PARENT_ID")) 
    @Enumerated(EnumType.STRING) 
    @Column (name="MY_ENUM", nullable=false) 
    public Set<MyEnum> getMyEnums(){ 
     return myEnums; 
    } 


public MyEnum { 
ENUM_A, 
ENUM_B, 
ENUM_C, 
ENUM_D; 
} 

ahora quiero buscar esta entidad con una colección de MyEnums. Solo las entidades donde todas las enumeraciones se establecen como en la colección de búsqueda deben ser devueltas. Así que si la entidad A tiene ENUM_A, ENUM_B y ENUM_C y la entidad B tiene ENUM_B, ENUM_C, ENUM_D una búsqueda con la colección de búsqueda ENUM_A, ENUM_B, ENUM_C solo debería devolver la entidad A. Una búsqueda de ENUM_B y ENUM_C no debería devolver nada.

¿Cómo haré eso en Hibernate? si hago

select p from Parent p where p.myEnums IN (:searchCollection) and size(p.myEnums) = size(:searchCollection) 

entonces esto sería volver ambas entidades para la primera búsqueda.

¿Alguna idea?

Actualización: Avancé un paso más al descubrir cómo hacerlo en MySQL pero al aplicar esto a Hibernate se genera un SQL no válido. Se podría usar una sub consulta con por él tienen gusto:

WHERE EXISTS(
    SELECT pa.PARENT_ID, count(pme.MY_ENUM) FROM PARENT pa, PARENT_MY_ENUM pme 
    where pa.PARENT_ID = pme.PARENT_ID 
    AND pme.MY_ENUM IN ('ENUM_A','ENUM_B') 
    GROUP BY pa.PARENT_ID HAVING count(pme.MY_ENUM) = 2 
) 

Pero cuando trato de hacer lo mismo en Hibernate:

select pa.ParentId, count(pa.myEnums) from Parent pa 
WHERE pa.myEnums IN ('ENUM_A','ENUM_B') 
GROUP BY pa.ParentId HAVING count(pa.myEnums) = 2 

Hiberante crea esta sentencia SQL:

select pa.CONTAINER_RELEASE_REFERENCE_ID as col_0_0_, count(.) as col_1_0_ from PARENT pa, PARENT_MY_ENUM enum1, PARENT_MY_ENUM enum2, PARENT_MY_ENUM enum3 
where pa.PARENT_ID=enum1.PARENT_ID and pa.PARENT_ID=enum2.PARENT_ID and pa.PARENT_ID=enum3.PARENT_ID 
and (. in ('ENUM_A' , 'ENUM_B')) 
group by pa.PARENT_ID having count(.)=2 

MySQL se queja del '.', ¿De dónde viene eso y por qué Hibernate usa 3 uniones con PARENT_MY_ENUM?

¿Es esto un error de Hibernate o qué estoy haciendo mal?

Respuesta

0

Dar el siguiente una oportunidad para que usted existe subselección

select pa.ParentId, count(en) from Parent pa join pa.myEnums as en 
WHERE en IN ('ENUM_A','ENUM_B') 
GROUP BY pa.ParentId HAVING count(en) = 2 

De lo contrario, me pregunto si algo así podría no hacer el trabajo

select p from Parent p join p.myEnums em 
where (:results) = elements(em) 

o

select p from Parent p join p.myEnums em 
where (:results) in elements(em) 
+0

Gracias a la unión extra en Enum hizo el truco. Muchas gracias – Ben

0

Creo que puedes hacer eso en java. Ejecute su consulta inicialmente propuesta, repita el resultado y excluya (iterator.remove()) los falsos positivos. Debería ser O(n), y creo que MySQL requerirá el mismo tiempo para filtrar su resultado.

+0

Podría ser lo mismo en términos de orden del problema; sin embargo, también debe tener en cuenta la cantidad de datos transferidos entre tabase y el servidor de aplicaciones (pueden o no estar en el mismo servidor). Digamos que solo el uno por ciento del conjunto de resultados realmente se ajustará a los criterios. Digamos que para ahorrar ancho de banda (y tiempo) entre el servidor de aplicaciones y la base de datos, establezca los resultados máximos en 100, solo terminará con una fila. Entonces, si bien esto podría ser una solución alternativa, en realidad no resuelve el problema. – Ben

Cuestiones relacionadas