Respostas:
Aqui está um trecho de hql que usamos. (Os nomes foram alterados para proteger as identidades)
String queryString = "select distinct f from Foo f inner join foo.bars as b" +
" where f.creationDate >= ? and f.creationDate < ? and b.bar = ?";
return getHibernateTemplate().find(queryString, new Object[] {startDate, endDate, bar});
É importante notar que a distinct
palavra - chave em HQL não mapeia diretamente para a distinct
palavra - chave em SQL.
Se você usar a distinct
palavra - chave em HQL, às vezes o Hibernate usará a distinct
palavra-chave SQL, mas em algumas situações ele usará um transformador de resultado para produzir resultados distintos. Por exemplo, quando você está usando uma junção externa como esta:
select distinct o from Order o left join fetch o.lineItems
Não é possível filtrar duplicatas no nível SQL neste caso, então o Hibernate usa um ResultTransformer
para filtrar duplicatas após a consulta SQL ter sido realizada.
faça algo assim da próxima vez
Criteria crit = (Criteria) session.
createCriteria(SomeClass.class).
setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
List claz = crit.list();
Você também pode usar Criteria.DISTINCT_ROOT_ENTITY
a consulta Hibernate HQL.
Exemplo:
Query query = getSession().createQuery("from java_pojo_name");
query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return query.list();
Tive alguns problemas com transformadores de resultado combinados com consultas HQL. Quando eu tentei
final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);
não funcionou. Tive que transformar manualmente assim:
final List found = trans.transformList(qry.list());
Com os transformadores Criteria API funcionou muito bem.
Minha consulta principal era assim no modelo:
@NamedQuery(name = "getAllCentralFinancialAgencyAccountCd",
query = "select distinct i from CentralFinancialAgencyAccountCd i")
E eu ainda não estava obtendo o que considerava resultados "distintos". Eles eram apenas distintos com base em uma combinação de teclas primárias na tabela.
Então, no DaoImpl
acrescentei uma mudança de linha e acabei obtendo o retorno "distinto" que queria. Um exemplo seria, em vez de ver 00 quatro vezes, agora vejo apenas uma vez. Aqui está o código que adicionei ao DaoImpl
:
@SuppressWarnings("unchecked")
public List<CacheModelBase> getAllCodes() {
Session session = (Session) entityManager.getDelegate();
org.hibernate.Query q = session.getNamedQuery("getAllCentralFinancialAgencyAccountCd");
q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); // This is the one line I had to add to make it do a more distinct query.
List<CacheModelBase> codes;
codes = q.list();
return codes;
}
Espero que tenha ajudado! Mais uma vez, isso pode funcionar apenas se você estiver seguindo as práticas de codificação que implementam o serviço, dao e tipo de projeto de modelo.
Suponha que você tenha uma Entidade do Cliente mapeada para a tabela CUSTOMER_INFORMATION e deseja obter uma lista de nomes distintos do cliente. Você pode usar o snippet abaixo para obter o mesmo.
Query distinctFirstName = session.createQuery("select ci.firstName from Customer ci group by ci.firstName");
Object [] firstNamesRows = distinctFirstName.list();
Espero que ajude. Então, aqui estamos usando group by em vez de palavras-chave distintas.
Também anteriormente achei difícil usar palavras-chave distintas quando desejo aplicá-las a várias colunas. Por exemplo, eu quero obter uma lista de firstName, lastName distintos e agrupar por simplesmente funcionaria. Tive dificuldade em usar distinto neste caso.
Eu tenho uma resposta para Hibernate Query Language para usar campos distintos. Você pode usar * SELECT DISTINCT (TO_CITY) FROM FLIGHT_ROUTE *. Se você usar a consulta SQL , ele retornará a Lista de String. Você não pode usar o valor de retorno por classe de entidade. Portanto, a resposta para resolver esse tipo de problema é usar HQL com SQL .
FROM FLIGHT_ROUTE F WHERE F.ROUTE_ID IN (SELECT SF.ROUTE_ID FROM FLIGHT_ROUTE SF GROUP BY SF.TO_CITY);
Da instrução de consulta SQL , obteve DISTINCT ROUTE_ID e entrou como uma lista. E a consulta IN filtra o TO_CITY distinto de IN (Lista).
O tipo de retorno é o tipo Entity Bean. Então você pode fazer isso em AJAX, como AutoComplement .
Que tudo fique bem
Você pode definir a palavra-chave distinta em seu construtor de critérios como este.
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Orders> query = builder.createQuery(Orders.class);
Root<Orders> root = query.from(Orders.class);
query.distinct(true).multiselect(root.get("cust_email").as(String.class));
E crie o construtor de campo em sua classe de modelo.
Se você precisar usar uma nova palavra-chave para um DTO personalizado em sua instrução select e precisar de elementos distintos , use new out of new como a seguir-
select distinct new com.org.AssetDTO(a.id, a.address, a.status) from Asset as a where ...