entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

2votos

Estoy tratando de realizar una consulta SQL utilizando safe CriteriaQuery en JPA 2, y me gustaria poder mostrar los resultados en una pagina JSF utilizando para ello un datatable.
Para la capa de la vista estoy utilizando PrimeFaces y la implementacion de JPA es EclipseLink.

Me gustaria mostrar una consulta del tipo:

select ges_venta_lineas.producto_id, sum(ges_venta_lineas.IMPORTETOTAL) from ges_venta_lineas group by ges_venta_lineas.producto_id

que utilizando CriteriaQuery quedaría esto.

public List<VentaLinea> getResumen(){
        CriteriaBuilder qb = em.getCriteriaBuilder();
        CriteriaQuery<VentaLinea> c = qb.createQuery(VentaLinea.class);
        Root<VentaLinea> root = c.from(VentaLinea.class);

        Expression<BigDecimal> sum = qb.sum(root.get(VentaLinea_.importeTotal));
        c.multiselect(root.get(VentaLinea_.producto), sum);
        c.groupBy(root.get(VentaLinea_.producto));
        Query query = getEntityManager().createQuery(c);
        return query.getResultList();
    }

Estoy recibiendo varios errores ya que al utilizar la funcion sum, se crea una nueva columna que no se corresponde con ningun campo de la clase VentaLinea por lo que entiendo que este metodo no debe devolver List<VentaLinea>, supongo que habrá una manera sencilla de hacerlo ya que lo que intento hacer no es nada del otro mundo, una posible solucion seria utilizar clases para "encapsular" el resultado de las consultas y poder devolver una lista de esa clase, pero me parece demasiado innecesario tener que crear una clase para cada posible consulta que quiera hacer.
Espero que alguien pueda ayudarme, un saludo.

1 Respuesta

2votos

MitsuGami Puntos8010

Utiliza NamedQueries para este tipo de consultas. La API de CriteriaBuilder es para queries con muchos valores dinámicos.

Suponiendo que tu entidad VentaLinea es así:

@Entity
@NamedQueries({
    @NamedQuery(name="VentaLinea.sumaImportes"
        query="SELECT v.id, SUM(v.importe) AS total FROM VentaLinea v GROUP BY v.id")
public class VentaLinea implements Serializable {

    @Id @GeneratedValue
    @Column(name="producto_id")
    private long id;
    @Column(name="IMPORTETOTAL")
    private BigDecimal importe;

    public VentaLinea() {}

    // constructores, getters y setters

}

Entonces solo debes llamar a esa NamedQuery en tu DAO:

public List<?> sumaImportes() {
    Query lineas = em.createNamedQuery("VentaLinea.sumaImpotes");
    return lineas.getResultList();
}

En tu backend bean, en el constructor utilizas el DAO para traer los valores del NamedQuery:

@Named
@RequestScoped
public class VentaLineaBean {

    private List<?> importes;
    @Inject
    private VentaLineaDao lineaDao;

    public VentaLineaBean() {
    importes = lineaDao.sumaImportes();
    }

    public List<VentaLinea> getImportes() {
    return importes;
    }

    // otros métodos
}

Y finalmente en tu vista, solo iteras esa lista:

<p:datatable var="array" value="#{ventaLineaBean.importes}" varStatus="loop">
    <p:column headerText="Id">
    <h:outputText value="#{array[loop.index]}" />
    </p:column>
    <p:column headerText="Total de importes">
    <h:outputText value="#{array[loop.index + 1]}" />
    </p:column>
</p:datatable>

PD: No he probado la expresión #{array[loop.index + 1]}, pero supongo debe funcionar.

0voto

Javi2EE comentado

Muchas gracias la verdad que no habia utilizado antes NamedQueries, pero para el caso de consultas estaticas es lo suyo. Gracias, solo una cosa, tengo que realizar tambien algunas consultas con valores dinamicos que utilizan campos de distintas tablas, sabrias como podría hacerlo, si es así abro otra pregunta nueva para no mezclar cosas en esta.

0voto

MitsuGami comentado

En ese caso, si es necesario CriteriaBuilder. Pero, si estás seguro que la query no cambia (es decir, los datos seleccionados) puedes seguir usando NamedQueries. Si los datos seleccionados cambian de acuerdo al suceso, es mejor CriteriaBuilder. Si tienes problemas con esa API abre un nuevo tema.

Saludos.

0voto

Peter comentado

@Javi2EE Si, mejor abre otra pregunta.

Saludos.

1voto

Javi2EE comentado

Vale, he abierto una nueva pregunta, dejo por aqui el enlace Consulta JPA a multiples tablas utilizando CriteriaBuilder

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta