Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Group by

Boa tarde!

Gostaria de produzir uma query semelhante a esta, so que em JPQL

select c.*, count(*) as qtd_movimentacoes from Conta c  join Movimentacao m on m.conta_id = c.id group by c.id;


+----+---------+-----------+-----------+---------------+-------------------+
| id | agencia | banco     | numero    | titular       | qtd_movimentacoes |
+----+---------+-----------+-----------+---------------+-------------------+
|  1 | 321     | Itau      | 123345    | Joao Ferreira |                 7 |
|  4 | 4526    | santander | 1084594-2 | Ramires       |                 2 |
+----+---------+-----------+-----------+---------------+-------------------+

Não estou conseguindo fazer isso no hibernate.

7 respostas

select c, count(c) from Conta c group by c.id

Só que o resultado dessa consulta será uma List já que ele não sabe como juntar os 2 resultados de cada linha em algum objeto. Dá uma procurada por "constructor expression".

Outro detalhe, não parece fazer muito sentido agrupar as contas por id quando vc não quer pegar nenhuma movimentação, mas aí já coisa do seu projeto :).

Olá Alberto, boa noite!

Talvez eu não tenha deixado isso muito claro, vou tentar elaborar minha pergunta melhor. Eu quero um relatório que me diga quantas movimentações cada conta teve.

select c.titular, count(*) as qtd_movimentacoes from Conta c  join Movimentacao m on m.conta_id = c.id group by c.titular;
+---------------+-------------------+
| titular       | qtd_movimentacoes |
+---------------+-------------------+
| Joao Ferreira |                 7 |
| Ramires       |                 2 |
+---------------+-------------------+

Pode não fazer muito sentido no contexto, mas acho que essa consulta seria o equivalente a, quantas vendas cada vendedor fez esse mês ou coisa desse tipo.

Nessa consulta que você me sugeriu, não vejo nenhuma ligação com movimentações, mas ainda sim escrevi o código que você postou. Ficou assim:

EntityManager entityManager = JPAUtil.getEntityManagerFactory();

        Query queryResult = entityManager
                .createQuery("select c,count(c) from Conta c group by c.id");

        List<Conta> listaDeContas = queryResult.getResultList();
        System.out.println(listaDeContas.get(0).getTitular());//erro de cast aqui

Acontece que ele da um erro de cast na linha em que eu tento imprimir uma conta, o que eu acho muito estranho. Você pode esclarecer isso para mim também ? Pois eu imaginava que me retornaria uma lista de contas.

Só uma observação. na última linha você fez uma consideração, mas minha consulta traz movimentações, e por isso agrupei por c.id, o que poderia ser qualquer outro atributo da conta, ou m.conta_id. Pelo menos no mysql é assim.

` select c.titular, count(m) from Conta c join c.movimentacoes m group by c.titular `

Como eu te disse acima, essa query vai retornar uma List e não um objeto do seu domínio. Você vai ter que tratar o retorno

Alberto, voce poderia me dizer como seria esse tratamento, porque eu não estou conseguindo fazer, não conheço java muito bem, você pode me dizer como fazer isso?

solução!

Oi Ramires, se vc não conhece muito bem java, acho que o mais importante é vc fazer os cursos mais básicos e depois voltar para fazer o de JPA. O código seria basicamente o seguinte:

List<Object[]> retorno = em.createQuery(...).getResultList();

List<RelatorioMovimentacoes> itens = new ArrayList<>();
for(Object[] info : retorno) {
  String titular = info[0];
  Number quantidade = (Number)info[1];
   itens.add(new RelatorioMovimentacoes(titular,quantidade));
}

Aí vc precisaria criar essa classe.. Daqui pra frente é com vc.

Deu certo Alberto, é isso mesmo.

Só um detalhe, o elemento de index 0(zero) é uma conta.


EntityManager entityManager = JPAUtil.getEntityManagerFactory();
        Query query = entityManager
                .createQuery("select c, count(c) from Conta c join c.movimentacoes group by c");
        List<Object[]> contas = query.getResultList();

        for (Object[] objects : contas) {
            Conta c = (Conta) objects[0];
            Number num = (Number) objects[1];
            System.out.println(c.getTitular() +" has "+num );
        }

muito obrigado mesmo Alberto.