tutorial example ejemplos hibernate jpa

hibernate - example - jpa ejemplos



org.hibernate.hql.ast.QueryTranslatorImpl list ATENCIÓN: firstResult/maxResults especificado con obtención de recopilación; aplicando en la memoria (3)

Estoy enfrentando un problema, tengo una consulta en JPA. como tengo algunas colecciones, necesito usar la búsqueda de unión izquierda o la búsqueda de unión interna

Mi problema es usar setFirstResult y setMaxResult para traer de vuelta un número preciso de resultados. cada vez que veo el resultado completo, vuelvo y solo DESPUÉS de que se use maxResult.

¿Hay alguna forma de hacer el maxResult antes?

Muchas gracias !

aquí hay más información:

mi problema es cuando uso eso:

startIndex = 0; maxResults = 10; query.setFirstResult(startIndex); query.setMaxResults(maxResults);

Veo este mensaje en mi registro:

7 juin 2011 09:52:37 org.hibernate.hql.ast.QueryTranslatorImpl list ATENCIÓN: firstResult / maxResults especificado con la recuperación de recopilación; aplicando en la memoria!

Veo el resultado de 200 volver (en el registro) y después en el HashSet tengo finalmente los 10 resultados que pido.

su parece en la memoria es devolver el resultado de 200 y después de que se aplique maxResults en la memoria.

Estoy buscando si hay alguna manera de poder buscar y limitar el número de resultados.

Utilicé una solución alternativa, realicé una primera consulta para solicitar el ID de mi pedido, sin ninguna búsqueda, utilicé el maxResult. todo funciona perfectamente, se usa la instrucción límite. Después de usar mi consulta "grande" con la búsqueda y limitar el resultado dentro de la lista de identificación traer de vuelta en la primera.

aquí está mi consulta completa sin mi solución alternativa (observe que no hay límite generado como conversación por @Bozho):

select o from Order o left join fetch o.notes note left join fetch o.orderedBy orderedBy left join fetch orderedBy.address addressOrdered left join fetch orderedBy.language orderedByLg left join fetch orderedByLg.translations orderedByLgTtrad left join fetch o.deliveredTo deliveredTo left join fetch deliveredTo.address addressDelivered left join fetch deliveredTo.language deliveredToLg left join fetch deliveredToLg.translations left join fetch o.finalReceiptPlace finalReceiptPlace left join fetch finalReceiptPlace.address addressFinalReceiptPlace left join fetch finalReceiptPlace.language finalReceiptPlaceLg left join fetch finalReceiptPlaceLg.translations inner join fetch o.deliveryRoute delivery left join fetch delivery.translations inner join fetch o.type orderType left join fetch orderType.translations inner join fetch o.currency currency left join fetch currency.translations left join fetch o.attachments left join fetch note.origin orig left join fetch orig.translations left join fetch o.supplier sup left join fetch sup.department dep left join fetch o.stateDetail stateD inner join fetch stateD.state stat where 1=1 and o.entryDate >= :startDat


setMaxResult (10) ajusta la consulta con otro resultado limitante, por ejemplo, para el oráculo:
seleccione * de ("su consulta aquí") donde rownum <10

Descubrí esto hoy durante la investigación de la consulta que tomó 64 segundos, ahora, lleva 1 segundo.

... lo mismo para criteria.setProjection (Projections.rowCount ()). setMaxResults (10)


Depende del motor DB usado ...

Tengo el mismo problema con Derby DB setFirstResult / setMaxResults no se utilizan.

ROW_NUMBER() OVER()... parece ser la solución.

Desafortunadamente, no encuentro cómo puedo generar tales solicitudes con JPA sin especificar toda la solicitud en SQL.


Para entender por qué Hibernate hace esto, necesita comprender cómo Hibernate hace el ORM (mapeo relacional de objetos) involucrado para las entidades JPA.

Considere un conjunto simplificado de Entidades para su pedido. Class Order contiene 2 campos: number y customerId y una lista de líneas de pedido. Class OrderLine contiene los campos productCode y quantity , así como una clave de uid y una referencia al pedido principal.

Estas clases se pueden definir así:

@Entity @Table(name = "ORDER") public class Order { @ID @Column(name = "NUMBER") private Integer number; @Column(name = "CUSTOMER_ID") private Integer customerId; @OneToMany(mappedBy = "order", fetch = FetchType.LAZY) @OrderBy private List<OrderLine> orderLineList; .... // Rest of the class } @Entity @Table(name = "ORDER_LINE") public class OrderLine { @ID @Column(name = "UID") private Integer uid; @Column(name = "PRODUCT_CODE") private Integer productCode; @Column(name = "QUANTITY") private Integer quantity; @Column(name = "ORDER_NUMBER") private Integer orderNumber; @ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "ORDER_NUMBER", referencedColumnName = "NUMBER", insertable = false, updatable = false) private Order order; .... // Rest of the class }

Ahora, si realizó la siguiente consulta JPQL en estas Entidades:

SELECT o FROM Order o LEFT JOIN FETCH o.orderLineList

luego Hibernate realiza esta consulta como una consulta SQL ''aplanada'' similar a la siguiente:

SELECT o.number, o.customer_id, ol.uid, ol.product_code, ol.quantity, ol.order_number FROM order o LEFT JOIN order_line ol ON order_line.order_number = order.number

que daría un resultado como este:

| o.number | o.customer_id | ol.uid | ol.product_code | ol.quantity | |==========|===============|========|=================|=============| | 1 | 123 | 1 | 1111 | 5 | | 1 | 123 | 2 | 1112 | 6 | | 1 | 123 | 3 | 1113 | 1 | | 2 | 123 | 4 | 1111 | 2 | | 2 | 123 | 5 | 1112 | 7 | | 3 | 123 | 6 | 1111 | 6 | | 3 | 123 | 7 | 1112 | 5 | | 3 | 123 | 8 | 1113 | 3 | | 3 | 123 | 9 | 1114 | 2 | | 3 | 123 | 10 | 1115 | 9 | ...etc

que Hibernate usaría para "reconstruir" objetos Order con listas adjuntas de sub-objetos OrderLine .

Sin embargo, dado que el número de líneas de pedido por pedido es aleatorio, no hay forma de que Hibernate sepa cuántas filas de esta consulta se deben realizar para obtener el número máximo especificado de objetos Order . Por lo tanto, tiene que tomar toda la consulta y crear los objetos en la memoria hasta que tenga la cantidad correcta, antes de descartar el resto del conjunto de resultados. La advertencia de registro que produce alude a esto:

ATTENTION: firstResult/maxResults specified with collection fetch; applying in memory!

Recién ahora estamos descubriendo que estas consultas pueden tener un impacto significativo en el uso de la memoria del servidor, y hemos tenido problemas con nuestro servidor que se cae con errores de falta de memoria cuando se intentan estas consultas.

Por cierto, diré ahora que esto es mayormente teoría de mi parte y no tengo idea de cómo funciona el código real de Hibernate. La mayor parte de esto se puede obtener de los registros cuando Hibernate registra las declaraciones SQL que genera.

ACTUALIZACIÓN: Recientemente he descubierto un poco de ''gotcha'' con lo anterior.

Considere una tercera entidad llamada Shipment que es para una o más líneas de una orden.

La entidad de Shipment tendría una asociación @ManyToOne con la entidad Order .

Supongamos que tiene 2 envíos para la misma orden que tiene 4 líneas.

Si realiza una consulta JPQL para lo siguiente:

SELECT s FROM Shipment s LEFT JOIN s.order o LEFT JOIN FETCH o.orderLineList

Esperaría (o al menos yo lo hice) recuperar dos objetos de envío, cada uno con una referencia al mismo objeto Order, que a su vez contendría las 4 líneas.

¡No, mal otra vez! De hecho, obtienes 2 objetos de envío, cada uno refiriéndose al mismo objeto Order, que contiene 8 líneas. Sí, las líneas se duplican en el pedido. Y sí, incluso si especifica la cláusula DISTINCT.

Si investigas este tema aquí en SO o en otro lugar (más notablemente en los foros de Hibernate), encontrarás que esto es realmente una característica, no un error, de acuerdo con los poderes de Hibernate. ¡Algunas personas realmente quieren este comportamiento!

Imagínate.