Ainda não tem acesso? Estude com a gente! Matricule-se
Ainda não tem acesso? Estude com a gente! Matricule-se

Solucionado (ver solução)

Retornar mais de um campo de atributo

Olá, legal esta aula quando utilizamos funções para retorno de nossas consultas. Tenho uma dúvida, como consigo voltar mais de um atributo usando o mesmo conceito? Por exemplo, gostaria de poder imprimir (System.out.printl) além da soma a descrição do tipo de conta.

Por exemplo, quero usar a seguinte JPQL:

SELECT m.tipo, SUM(m.valor) FROM Movimentação m

Quero poder acessar os dois atributos e imprimi-los.

Att.

José Luiz

4 respostas

Veja se os exemplos desta aula ajudam:

https://cursos.alura.com.br/course/persistencia-de-objetos-com-jpa-hibernate/task/24974

Ola Gabriel, nos vídeos ele esta retornando o objeto com todos os seus campos apesar de estar imprimindo somente os campos que ele quer.

O que eu quero é não retornar o objeto completo (Quero que este retorno seja customizado).

Pesquisando encontrei uma solução que me atende porém trabalho com Spring Data JPA, não tentei fazer com hibernate, mas acredito que funcione da mesma forma.

Deixo embaixo a forma de utilização para caso alguém queira testar.

Primeiro criei a classe que será vista como a entidade no meu modelo.

@Entity
public class Galinha

    @Id
    private Long id;
    private String raca; //Raça
    private Int qtdOvos;

    Get and Set ....

Aqui mostro cada objeto Galinha criado e a quantidade de ovos colocadas por cada uma:

id1 - Galinha Angola - 3 
id2 - Galinha Granja - 2
id3 - Galinha Caipira - 2
id4 - Galinha Granja - 5
id5 - Galinha Caipira - 2
id6- Galinha Caipira - 4
id7- Galinha Angola - 1

1) Quero por exemplo executar a seguinte instrução

Select distinct g.raca, SUM(g.qtdOvos) as total from Galinha g

Sei que se estivesse trabalhando somente com um campo seria simples retorná-lo ainda que eu tivesse que ficar utilizando Cast. O problema é quando temos mais de um campo igual ao nosso exemplo. Vi alguns exemplos pela internet onde se retornava um vetor de Object:

List<Object[]> galinhas = q.getResultList();

for (Object[] a : galinhas) {
    System.out.println("Raça:  " + a[0])
    System.out.println("Quantidade:  " + a[1])
}
`

Mas sinceramente trabalhar com vetor para retornar o campo que eu quero deste objeto achei que fica meio estranho, (Por exemplo, se em minha consulta gerar um objeto de 20 campos dificilmente vou saber o que é o object[12].

Mas pesquisando consegui encontrar uma abordagem melhor, pelo menos ao utilizar o Spring Data JPA.

Com @SqlResultSetMapping consigo fazer com que o meu retorno da query seja do tipo customizado que eu defini, vamos lá...

Criei uma classe que será utilizada como o tipo dos objetos de retorno de minha query:

public class GalinhaResumo {
    private String raca;
    private Int total;
    Get and Set ....

Depois utilizei sobre a classe entidade a anotação @SqlResultSetMapping onde disse o que cada campo seria, mantendo o cuidado de manter cada campo na mesma posição ocupada pelo atributo relacionado no retorno da query.

@SqlResultSetMapping(
        name = "GalinhaResumo",
        classes = @ConstructorResult(
                targetClass = GalinhaResumo.class,
                columns = {
            @ColumnResult(name = "raca"),
            @ColumnResult(name = "total", Type= Int.class)})

@Entity
public class Galinha
    @Id
    private Long id;
    private String raca; //Raça
    private Int qtdOvos;
    Get and Set ....

Legal, por fim utilizando o método createNativeQuery do EntityManager coloquei que o retorno da consulta seriam objetos do tipo GalinhaResumo (Obs.: no código em é um objeto do tipo Entity Manager):

Query q = em.createNativeQuery = ("Select distinct g.raca as raca, SUM(g.qtdOvos) as total from Galinha g", "GalinhaResumo");

List<GalinhaResumo> galinhas = q.getResultList();

Agora consigo acessar os atributos da seguinte forma:

for (GalinhaResumo g : galinhas) {
    System.Out.Println("Raça: " + g.raca);
    System.Out.Println("Quantidade: " + total)
}

acho que o código fica mais semântico desta forma.

solução

Boa, José!

Pode também usar as projections da JPQL:

List<ProdutoDTO> produtos = entityManager
.createQuery("select new br.com.caelum.dto.ProdutoDTO(p.nome, p.preco) from Produto p", ProdutoDTO.class)
.getResultList();

Outra opção é fazer o mapeamento do resultado, manualmente, com ResultTransformer (se tiver usando Hibernate).

abs!

Valeu Leonardo, rodou legal aqui.