subselect lazy joins inner initialize java hibernate join hql fetch

java - lazy - jpql fetch join



Diferencia entre JOIN y JOIN FETCH en Hibernate (4)

Por favor, ayúdame a entender dónde usar un JOIN regular y dónde unir FETCH.

Por ejemplo, si tenemos estas dos consultas

FROM Employee emp JOIN emp.department dep

y

FROM Employee emp JOIN FETCH emp.department dep

¿Hay alguna diferencia entre ellos? Si es así, ¿cuál usar cuando?


Dherik: No estoy seguro de lo que dices, cuando no usas fetch, el resultado será de tipo: List<Object[ ]> que significa una lista de tablas Object y no una lista de Employee.

Object[0] refers an Employee entity Object[1] refers a Departement entity

Cuando usa fetch, solo hay una selección y el resultado es la lista de Employee List<Employee> contiene la lista de departamentos. Anula la declaración perezosa de la entidad.


En estas dos consultas, utiliza JOIN para consultar a todos los empleados que tienen asociado al menos un departamento.

Pero, la diferencia es: en la primera consulta solo devuelve los Employes para Hibernate. En la segunda consulta, está devolviendo los Empleados y todos los departamentos asociados.

Por lo tanto, si utiliza la segunda consulta, no necesitará hacer una nueva consulta para volver a acceder a la base de datos y ver los departamentos de cada empleado.

Puede usar la segunda consulta cuando esté seguro de que necesitará el Departamento de cada Empleado. Si no necesita el Departamento, use la primera consulta.

Recomiendo leer este enlace si necesita aplicar alguna condición WHERE (lo que probablemente necesite): ¿Cómo expresar JPQL correctamente "juntar búsqueda" con la cláusula "where" como JPA 2 CriteriaQuery?

Actualizar

Si no usa fetch y los Departments continúan siendo devueltos, se debe a que su asignación entre Employee y Department (un @OneToMany ) está FetchType.EAGER con FetchType.EAGER . En este caso, cualquier consulta HQL (con fetch o no) con FROM Employee traerá todos los departamentos. Recuerde que todos los mapas * ToOne ( @ManyToOne y @OneToOne ) son EAGER por defecto.


Si tiene el mapeo @oneToOne establecido en FetchType.LAZY y utiliza la segunda consulta (porque necesita que los objetos del Departamento se carguen como parte de los objetos del Empleado) lo que Hibernate hará es emitir consultas para obtener objetos del Departamento para cada objeto Empleado individual obtiene de DB. Más adelante en el código, puede acceder a los objetos del Departamento a través de la asociación de valor único de empleado a departamento e Hibernate no emitirá ninguna consulta para obtener el objeto del Departamento para el empleado dado. Recuerde que Hibernate aún emite consultas equivalentes a la cantidad de Empleados que ha obtenido. Hibernate emitirá el mismo número de consultas en las dos consultas anteriores si desea acceder a los objetos del Departamento de todos los objetos del Empleado


en link mencioné antes en el comentario, lea esta parte:

Una unión "fetch" permite inicializar asociaciones o colecciones de valores junto con sus objetos principales usando una única selección. Esto es particularmente útil en el caso de una colección. Con eficacia anula la combinación externa y las declaraciones vagas del archivo de asignación para asociaciones y colecciones.

este "JOIN FETCH" tendrá su efecto si tiene la propiedad (fetch = FetchType.LAZY) para una colección dentro de la entidad (ejemplo abajo).

Y solo tiene efecto el método de "cuando la consulta debería suceder". Y también debes saber this :

Hibernate tiene dos nociones ortogonales: ¿cuándo se busca la asociación y cómo se obtiene? Es importante que no los confundas. Usamos fetch para ajustar el rendimiento. Podemos usar lazy para definir un contrato para qué datos están siempre disponibles en cualquier instancia separada de una clase en particular.

Cuándo se obtiene la asociación -> su tipo "FETCH"

cómo se obtiene -> Unir / seleccionar / Subseleccionar / Lote

En su caso, FETCH solo tendrá efecto si tiene el departamento como un conjunto dentro de Employee, algo así en la entidad:

@OneToMany(fetch = FetchType.LAZY) private Set<Department> department;

cuando usas

FROM Employee emp JOIN FETCH emp.department dep

obtendrás emp y emp.dep . cuando no emp.dep fetch todavía puedes obtener emp.dep pero hibernate procesará otra selección en la base de datos para obtener ese conjunto de departamento.

así que solo es cuestión de ajustar el rendimiento, de que desea obtener todos los resultados (lo necesita o no) en una sola consulta (obtención ansiosa), o si desea consultarlos más tarde cuando lo necesite (recuperación diferida).

Utilice la búsqueda ansiosa cuando necesite obtener datos pequeños con una sola selección (una consulta grande). O use la recuperación diferida para consultar qué necesita más tarde (muchas consultas más pequeñas).

use buscar cuando:

  • no hay grandes colecciones / conjuntos innecesarios dentro de esa entidad a punto de obtener

  • comunicación desde el servidor de aplicaciones al servidor de bases de datos demasiado lejos y necesita mucho tiempo

  • es posible que necesite esa recopilación más tarde cuando no tenga acceso ( fuera del método / clase transaccional )