Pergunta

Não tenho certeza de como descrever esse problema, então acho que um exemplo é a melhor maneira de fazer minha pergunta:

Eu tenho duas mesas com um relacionamento de muita tomana:

Driverslicence <-> licenceclass

Licenceclass é coisas como "carro", "motocicleta" e "médio rígido".

Usando os critérios de hibernação, como posso encontrar todas as licenças que possuem licencasses de "carro" e "motocicleta"?

ATUALIZAÇÃO 11/12/2008 Descobri que isso pode ser facilmente alcançado usando um resultante de resultado personalizado. No entanto, o problema é que um transformador de resultado é aplicado apenas após a consulta retornar seus resultados, na verdade não se torna parte do SQL. Então, acho que minha pergunta é agora "Você pode fazer o que descrevi inicialmente no SQL - e existe um analógico de critério de hibernação?"

Foi útil?

Solução

Veja como finalmente consegui isso 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();
}

Ou usando os critérios de hibernato com um 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));
}

LECENCE_CLASS_JOIN_TABLE é o nome da tabela que o Hibernate gera para suportar a relação muitos para muitos entre o Driverslicence e o Licenceclass.

Outras dicas

Você ainda pode usar a notação do DOT para trabalhar nas relações. Por exemplo, supondo que você tenha uma propriedade DriverSlicence.licenceclass e propriedade LicEnceclass.type, então:

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

Pessoalmente, porém, eu simplesmente evitaria o uso de critérios neste caso, porque não é uma consulta dinâmica, mas, em vez disso, usará:

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

Eu tive um problema semelhante, mas corrigi -me usando o HQL, tenho uma classe "Enterprise" relacionada à classe "usuário" e também relacionada à "função de classe", eles estão muitos para muitos relacionamentos, quando preciso de todas as empresas relacionadas Para um usuário específico, faço o seguinte;

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

Suponho que, no seu caso, você deve fazer 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 ajude.

Outra opção é fazer as junções de corrente (uma junção por cada Licenseclass). Eu usei o construtor de critérios e 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 o dlroot é objeto da classe raiz e você pode obtê -la da classe de critério. O predicado resultado é o que você está procurando ...

'Eu não acho que isso vai funcionar. Eu quero encontrar todas as licenças que têm Ambas "Carro" e "motocicleta" '

Expressão do usuário. E (....) em vez de expressão.or (....) no trecho fornecido por nick

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top