Este es un problema similar a: HQL – identificador de fila para la paginación

Estoy tratando de implementar la paginación usando HQL. Tengo una base de datos PostgreSQL.

int elementsPerBlock = 10;
int page = 2; //offset = 2*10

String sqlQuery = "FROM Messages AS msg " +
                  " LEFT JOIN FETCH msg.commands AS cmd " +   
                  "ORDER BY msg.identifier ASC" ;

Query query = session.createQuery( sqlQuery )
                     .setFirstResult( elementsPerBlock * ( (page-1) +1 ) )
                     .setMaxResults( elementsPerBlock );

Lo que pasa es que Hibernan recupera TODOS los Mensajes, y devuelve los necesarios después estaban todos cargados.

Por lo tanto, Hibernate recupera 210000 entidades en lugar de los 30 que se devuelven (cada uno de los Mensajes tiene exactamente 2 comandos).

Hay una manera de reducir la sobrecarga por un factor de 7000?

edit: he intenta agregar .setFetchSize( elementsPerBlock ) . No ayuda.

edit 2: la consulta SQL que se genera es:

select ... 
from schemaName.messages messages0_ 
left outer join schemaName.send_commands commands1_ 
on messages0_.unique_key=commands1_.message_key 
order by messages0_.unique_identifier ASC

Absolutenly ningún LÍMITE o DESPLAZAMIENTO

  • eso podría ser un error. se puede habilitar la depuración parámetro para mostrar las consultas SQL y ver la consulta real ejecutado por favor?
  • la consulta SQL no tenía absolutamente ningún LÍMITE o DESPLAZAMIENTO
  • setFirstResult( elementsPerBlock * ( (page-1) +1 ) ) El «-1 +1» no parece ser correcto aquí :o)
InformationsquelleAutor iliaden | 2011-06-14

6 Comentarios

  1. 15

    Por el JPA 2.0 de la especificación, sección 3.8.6 la Ejecución de la Consulta,

    El efecto de la aplicación de setMaxResults
    o setFirstResult a una consulta de
    fetch se une a más de colecciones
    indefinido.

    Varía de una base de datos a la base de datos, y en mi experiencia, el resultado es de Hibernación por lo general tiene la paginación de memoria en lugar de en la base de datos a nivel de consultas.

    Lo he hecho generalmente se utiliza una consulta independiente para obtener los identificadores de los objetos deseados, y de paso que en la consulta con la captura de combinación.

    • ¿Cómo puede usted utilizar la paginación con una subselección? (Entiendo que la segunda idea, pero entonces mi comunicación puede ser muy hablador)
    • Editado para eliminar la referencia a subselección. De hecho derrotas el propósito entero si utiliza una subselección.
    • aunque se acabaría con el propósito, quiero que todos los cálculos a realizar en la DB lado en lugar de en el lado del cliente. Esta es la razón por la que yo creo que si una subselección puede hacer la paginación, se debería usar.
    • Yo no creo que una subselección puede hacer la paginación. No hay daño en el intento, por supuesto.
  2. 7

    estoy usando esta solución:

    /**
     * @param limitPerPage
     * @param page
     * @return
     */
    public List<T> searchByPage(int limitPerPage, int page, String entity) {
        String sql = "SELECT t FROM " + entity + " t";
        Query query = em.createQuery(sql)
                .setFirstResult(calculateOffset(page, limitPerPage))
                .setMaxResults(limitPerPage);
        return query.getResultList();
    }
    
    /**
     * @param page
     * @return
     */
    private int calculateOffset(int page, int limit) {
        return ((limit * page) - limit);
    }

    De bienvenida.

    • ¿por qué no traducir al inglés ?
    • He traducido para el portugués tanto en inglés de código, cuando no sé lo que la palabra significa… ¿por qué no se puede hacer lo mismo?
  3. 1

    Más probablemente, si usted crear su propia consulta con HQL, el generador de consultas de los métodos no se puede analizar personalizado de consulta hql y alterarlo. Por lo tanto, usted debe poner su LIMIT ?, ? declaración al final de su consulta HQL y enlazar parámetros de desplazamiento, a continuación,.

    • Estoy teniendo algunos problemas para entender lo que quieres decir. 1) ¿cómo puedo añadir una cadena al final de una consulta HQL? 2) ¿qué entiende usted por «enlazar parámetros de desplazamiento» ?
  4. 1

    Ya que no filtrar el conjunto de resultados con respecto a algunos de los atributos de comando entidad, también se puede evitar el join de SQL y configurar la recuperación perezosa para mensaje‘s comandos. Sin unir, Hibernate emplear la base de datos de paginación cabilities.

    Sin embargo, usted tiene cuidado sobre el N+1 seletcs problema, es decir, evitando una selección única para cada perezosamente recuperan comandos atributo. Usted puede evitar esto mediante el establecimiento de la lote de tamaño propiedad en su mapeo hibernate o globalmente la de hibernación.default_batch_fetch_size de la propiedad en la configuración de la hibernación.

    Por ejemplo: Si se han recuperado 100 mensaje objetos dentro de una sesión de Hibernate y establecer un lote de tamaño de 10, Hibernate obtendrá 10 comando asociaciones de 10 diferentes objetos de los mensajes cuando llame primero a getCommands() de un mensaje objeto. El número de consultas se reduce a 10 más el mensaje original-ir a buscar uno.

    Echa un vistazo aquí: http://java.dzone.com/articles/hibernate-tuning-queries-using?page=0,1 El autor compara las diferentes fetch estrategias para un ejemplo simple

  5. 1

    Podemos lograr la paginación mediante de Consulta y los Criterios de interfaz:

    La paginación de usar Interfaz de Consulta:

    Hay dos métodos de la interfaz de Consulta para la paginación.

    1. Consulta setFirstResult(int startPosition):
    Este método toma un entero que representa la primera fila en el conjunto de resultados, empezando por la fila 0.

    2. Consulta setMaxResults(int maxResult):
    Este método le dice a Hibernate para recuperar un número fijo maxResults de los objetos. El uso de dos métodos anteriores juntos, podemos construir una paginación componente en nuestra web o aplicación Swing.

    Ejemplo:

    Query query = session.createQuery("FROM Employee");
    query.setFirstResult(5);
    query.setMaxResults(10);
    List<Employee> list = query.list();
    for(Employee emp: list) {            
       System.out.println(emp);
    }

    La paginación usando los Criterios de la Interfaz:

    Hay dos métodos de los Criterios de la interfaz para la paginación.

    1. Criterios de setFirstResult(int firstResult):

    Establecer el primer resultado obtenido.

    2. Elemento de la lista de Criterios setMaxResults(int maxResults):

    Establecer un límite sobre el número de objetos a ser recuperada.

    Ejemplo:

    Criteria criteria = session.createCriteria(Employee.class);
    criteria.setFirstResult(5);
    criteria.setMaxResults(10);            
    List<Employee> list = criteria.list();
    for(Employee emp: list) {            
        System.out.println(emp);
    }
    • ¿Has probado esto? Stevi Disuadir dice que el efecto de esto es indefinido.
    • ¿Cuál es el efecto?
  6. 0

    Creo que su original excepción no es correcto.

    Lo que pasa es que Hibernan recupera TODOS los Mensajes, y >devuelve los necesarios después estaban todos cargados.

    Lo que ocurre durante el procesamiento de la consulta es que setFirstResult(calculateOffset(página, limitPerPage)) se traduce al DESPLAZAMIENTO y setMaxResults(limitPerPage) se traduce al LÍMITE

Dejar respuesta

Please enter your comment!
Please enter your name here