Pregunta

No estoy seguro de cómo describir este problema, así que creo que un ejemplo es la mejor manera de hacer mi pregunta:

Tengo dos tablas con una relación manyToMany:

DriversLicence < - > LicenceClass

LicenceClass es cosas como " Car " ;, " Moto " ;, y " Rígido medio " ;.

Usando los Criterios de Hibernación, ¿cómo puedo encontrar todas las licencias que tienen " Car " y " Moto " LicenceClasses?

ACTUALIZACIÓN 12/11/2008 He descubierto que esto se puede lograr fácilmente utilizando un ResultTransformer personalizado. Sin embargo, el problema es que un transformador de resultados solo se aplica DESPUÉS de que la consulta devuelve sus resultados, en realidad no se convierte en parte del SQL. Así que supongo que mi pregunta ahora es & "; ¿Puedes hacer lo que describí inicialmente en SQL - y hay un análogo de Criterios de Hibernación? &";

¿Fue útil?

Solución

Así es como finalmente lo logré usando HQL:

public List<DriversLicence> findDriversLicencesWith(List<LicenceClass> licenceClasses) {
    String hqlString = "select dl from DriversLicenceImpl dl where 1=1 ";
    for (int i = 0; i < licenceClasses.size(); i++) {
        hqlString += " and :licenceClass" + i + " = some elements(dl.licenceClasses)";
    }

    Query query = getSession().createQuery(hqlString);
    for (int i = 0; i < licenceClasses.size(); i++) {
        query.setParameter("licenceClass" + i, licenceClasses.get(i));
    }
    return query.list();
}

O usando los Criterios de Hibernación con una sqlRestriction:

for (LicenceClass licenceClass : licenceClasses) {               
    criteria.add(Restrictions.sqlRestriction("? = some(select " + LicenceClass.PRIMARY_KEY + " from " +
                    LICENCE_CLASS_JOIN_TABLE + "  where {alias}." +
                    DriversLicence.PRIMARY_KEY + " = " + DriversLicence.PRIMARY_KEY + ")",
                    licenceClass.getId(), Hibernate.LONG));
}

LICENCE_CLASS_JOIN_TABLE es el nombre de la tabla que genera la hibernación para soportar la relación de muchos a muchos entre driversLicence y LicenceClass.

Otros consejos

Todavía puede usar la notación de puntos para trabajar a través de las relaciones. Por ejemplo, suponiendo que tiene una propiedad DriversLicence.licenceClass y una propiedad LicenceClass.type, entonces:

session.createCriteria(DriversLicence.class)
   .add(Expression.or(
     Expression.eq("licenceClass.type", "Car"),
     Expression.eq("licenceClass.type", "Motorbike")
   )
).list();

Personalmente, simplemente evitaría usar criterios en este caso porque no es una consulta dinámica, sino que usaría:

session.createQuery("from DriversLicence where licenceClass.type in (:types)")
  .setParameterList("types", myListOfTypes)
  .list();

Tuve un problema similar pero lo solucioné usando HQL, tengo una clase " Enterprise " que está relacionado con la clase " Usuario " y también relacionado con la clase " Role " ;, tienen una relación de muchos a muchos, cuando necesito todas las empresas relacionadas con un usuario específico hago lo siguiente;

Select e from Enterprise As e inner join e.Users As u inner join u.Roles As r 
Where u.UserCode=?

Supongo que en tu caso deberías hacer algo como;

Select dl from LicenceClass As l inner join l.DriversLicences As dl
Where 
l.LicenseClass.Name = ? OR 
l.LicenseClass.Name=? OR 
l.LicenseClass.Name=?

Espero que ayude.

Otra opción es encadenar combinaciones (una combinación por cada LicenseClass). Usé un generador de criterios y predicados como este

 List<Predicate> predicates = new ArrayList<>();
 for(Integer lcId : licenceClassIdList) {
     SetJoin<DriversLicence, LicenceClass> dlClasses = dlRoot.join(DriversLicence_.licenceClasses);
     predicates.add(builder.equal(dlClasses.get(LicenseClass_.id), lcId));
 }
 Predicate predicate = builder.and(predicates.toArray(new Predicate[predicates.size()]));

Observe que dlRoot es objeto de la clase Root y puede obtenerlo de la clase CriteriaQuery. El predicado resultante es lo que estás buscando ...

'No creo que esto vaya a funcionar. Quiero encontrar todas las licencias que tienen ambas & Quot; Car & Quot; y " Moto " '

User Expression.and (....) en lugar de Expression.or (....) en el fragmento proporcionado por Nick

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top