2011-01-27 13 views
5
estructura

objeto es asíRecuperar una estructura gráfica en Hibernate

  • factura
    • cliente
    • Fecha
    • Número
    • tiene muchas ProductLines (producto, cantidad, precio)
    • tiene muchas líneas de servicio (servicio, cantidad, precio)
    • tiene muchas PaymentOptions (TipoPago (Cheque, recibos, etc.), Fecha, SUM)

Si necesito para recuperar una lista de facturas durante un período determinado con Hibernate es muy fácil de hacer con perezosa cargando sin escribir ningún código simplemente llame a get ... PERO existe la desventaja de demasiadas llamadas a bases de datos, por lo que en un entorno multiusuario esta solución no está bien.

Con JDBC simple resolví esto usando 3 consultas: 3 uniones entre Factura y ProductLines, Factura y Líneas de servicio y Factura y Opciones de pago. Después de eso construí el objeto en la memoria.

Lo mismo se puede hacer con Hibernate Sé, PERO mi pregunta es que no hay tal cosa como cargar el gráfico o puedo pasar una lista de facturas y en un número mínimo de llamadas (óptima) para recuperar los datos?

Respuesta

4

Puede utilizar consultas con join para obtener todo el gráfico de objetos en la memoria:

Query query = entityManager.createQuery("select distinct invoice from Invoice as invoice " 
      + "left join fetch invoice.productLines "     
      + "left join fetch invoice.serviceLines " 
      + "left join fetch invoice.paymentOptions"); 
for (Object object : query.getResultList()) { 
    // Code here 
} 
+1

Sí, eso es resolver el problema en una consulta. El único inconveniente es que el producto cartesiano de todas estas tablas puede ser enorme, ¿no? – Cris

+1

De hecho. Sin embargo, con este método siempre puede elegir qué asociaciones buscar de inmediato y cuáles cargar de forma perezosa.Entonces puede usar el tamaño del lote, como sugirió Simon, para acelerar las recuperaciones de los perezosos. –

+1

+1 para el ejemplo, que he agregado a mi respuesta. –

4

Puede que desee considerar batch fetching para sus líneas de factura y búsqueda de muchas asociaciones como Cliente.

Esto no lo llevará a una sola llamada de base de datos, pero si sintoniza los tamaños de lote para exceder ligeramente el número promedio de líneas de cada tipo en una factura, puede obtener uno por tipo de línea.

También podría consulta utilizando JPQL/HQL y explícitamente en la descarga a unirse a las líneas (as Russ decribes), pero se obtiene un resultado conjunto más amplio que lo haría con un enfoque de recuperación en lotes:

Query query = entityManager.createQuery("select distinct invoice from Invoice as invoice " 
      + "left join fetch invoice.productLines "     
      + "left join fetch invoice.serviceLines " 
      + "left join fetch invoice.paymentOptions"); 
for (Object object : query.getResultList()) { 
    // Code here 
} 

Si el tamaño de los datos brutos transferidos resultan ser demasiado altos, puede deshabilitar la captación de forma explícita al eliminar "buscar" de la consulta en los lugares relevantes.

Tenga en cuenta que existe un problema de mantenimiento al usar JPQL porque el compilador no puede verificar todos los nombres de propiedad y si la recuperación es desactivada para todas las asociaciones, la consulta tiene un costo neto. Puede comenzar con la búsqueda por lotes si el rendimiento no es un problema inmediato.

+0

que me puso en la dirección correcta (desafortunadamente no puedo darle un voto ya no se me permite todavía) .Gracias, – Cris

+1

Las consultas con nombre se pueden usar para resolver el problema del nombre de la propiedad; se pueden verificar fácilmente en una prueba unitaria. La consulta en tiempo de ejecución fue solo para reducir el tamaño del ejemplo: siempre se deben usar las consultas con nombre. –

Cuestiones relacionadas