Soy un novato en Java Persistence API e Hibernate.
¿Cuál es la diferencia entre FetchType.LAZY
y FetchType.EAGER
en Java Persistence API?
Soy un novato en Java Persistence API e Hibernate.
¿Cuál es la diferencia entre FetchType.LAZY
y FetchType.EAGER
en Java Persistence API?
Respuestas:
A veces tienes dos entidades y hay una relación entre ellas. Por ejemplo, puede tener una entidad llamada
University
y otra entidad llamadaStudent
y una universidad puede tener muchos estudiantes:La entidad universitaria puede tener algunas propiedades básicas, como id, nombre, dirección, etc., así como una propiedad de colección llamada estudiantes que devuelve la lista de estudiantes de una universidad determinada:
Ahora, cuando carga una universidad desde la base de datos, JPA carga sus campos de identificación, nombre y dirección por usted. Pero tiene dos opciones sobre cómo deben cargarse los estudiantes:
getStudents()
método de la universidad .Cuando una universidad tiene muchos estudiantes, no es eficiente cargar a todos sus estudiantes junto con ella, especialmente cuando no son necesarios y, en tales casos, puede declarar que desea que los estudiantes se carguen cuando realmente se necesitan. Esto se llama carga diferida.
Aquí hay un ejemplo, donde
students
está marcado explícitamente para cargarse con entusiasmo:Y aquí hay un ejemplo donde
students
está marcado explícitamente para ser cargado perezosamente:fuente
getStudents()
. Ej. ), Pero a veces esto no es posible, porque para cuando este método se llama, la sesión ya está cerrada y la entidad separada. Del mismo modo, a veces tenemos una arquitectura cliente / servidor (por ejemplo, cliente Swing / servidor JEE) y las entidades / DTO se transfieren a través del cable al cliente y nuevamente en estos escenarios la carga diferida no funcionará debido a la forma en que las entidades se serializan a través del cable.getStudents()
método por primera vez, ¿se guardan en caché los resultados? para poder acceder a esos resultados más rápido la próxima vez?Básicamente,
fuente
EAGER
la carga de colecciones significa que se recuperan completamente en el momento en que se recupera su padre. Entonces, si tieneCourse
y tieneList<Student>
, todos los estudiantes se obtienen de la base de datos en el momento en queCourse
se obtiene.LAZY
por otro lado, significa que los contenidos de losList
archivos solo se obtienen cuando intenta acceder a ellos. Por ejemplo, llamandocourse.getStudents().iterator()
. Llamar a cualquier método de acceso en elList
iniciará una llamada a la base de datos para recuperar los elementos. Esto se implementa creando un Proxy alrededor deList
(oSet
). Entonces, para sus colecciones perezosas, los tipos concretos no sonArrayList
yHashSet
, sinoPersistentSet
yPersistentList
(oPersistentBag
)fuente
course.getStudents()
, dispara una consulta SQL (lo vi en la consola). En el tipo de recuperación diferida también, sucede lo mismo. Entonces, ¿cuál es la diferencia?fetchtype = LAZY
el predeterminado, incluso si intenta obtener la colección con el getter hibernete arroja un error diciéndome que no puede evaluarPuedo considerar el rendimiento y la utilización de la memoria. Una gran diferencia es que la estrategia de recuperación EAGER permite utilizar objetos de datos recuperados sin sesión. ¿Por qué?
Todos los datos se obtienen cuando los datos marcados ansiosos en el objeto cuando se conecta la sesión. Sin embargo, en el caso de una estrategia de carga diferida, el objeto marcado de carga diferida no recupera datos si la sesión se desconecta (después de la
session.close()
declaración). Todo lo que puede hacer el proxy de hibernación. La estrategia entusiasta permite que los datos sigan disponibles después de cerrar la sesión.fuente
Según mi conocimiento, ambos tipos de búsqueda dependen de sus requisitos.
FetchType.LAZY
está bajo demanda (es decir, cuando requerimos los datos).FetchType.EAGER
es inmediato (es decir, antes de que llegue nuestro requisito, estamos recuperando el registro innecesariamente)fuente
De forma predeterminada, para todos los objetos de colección y mapa, la regla de obtención es
FetchType.LAZY
y para otras instancias sigue laFetchType.EAGER
política.En resumen,
@OneToMany
y las@ManyToMany
relaciones no obtienen los objetos relacionados (colección y mapa) implícitamente, pero la operación de recuperación se conecta en cascada a través del campo en@OneToOne
y@ManyToOne
unos.(cortesía: - objectdbcom)
fuente
Ambos
FetchType.LAZY
yFetchType.EAGER
se utilizan para definir el plan de recuperación predeterminado .Desafortunadamente, solo puede anular el plan de recuperación predeterminado para la recuperación PERFECTA. La obtención de EAGER es menos flexible y puede generar muchos problemas de rendimiento .
Mi consejo es contener el impulso de hacer que sus asociaciones sean EAGER porque buscar es una responsabilidad de tiempo de consulta. Por lo tanto, todas sus consultas deben usar la directiva fetch para recuperar solo lo necesario para el caso de negocios actual.
fuente
Del Javadoc :
Por ejemplo, ansioso es más proactivo que perezoso. Lazy solo ocurre en el primer uso (si el proveedor toma la indirecta), mientras que con cosas ansiosas (puede) pretrabarse.
fuente
El
Lazy
tipo de recuperación se selecciona de forma predeterminada por Hibernate a menos que marque explícitamente elEager
tipo de recuperación. Para ser más exacto y conciso, la diferencia se puede establecer de la siguiente manera.FetchType.LAZY
= Esto no carga las relaciones a menos que lo invoque a través del método getter.FetchType.EAGER
= Esto carga todas las relaciones.Pros y contras de estos dos tipos de búsqueda.
Lazy initialization
mejora el rendimiento al evitar cálculos innecesarios y reduce los requisitos de memoria.Eager initialization
requiere más consumo de memoria y la velocidad de procesamiento es lenta.Dicho esto, depende de la situación, cualquiera de estas inicializaciones puede ser utilizada.
fuente
getMember
se llame a una función llamada que coincida exactamente con el patrón de nombre del miembro?Book.java
Sujeto.java
HibernateUtil.java
Main.java
Verifique el método retrieve () de Main.java. Cuando obtengamos Asunto, su lista de colección Libros , anotada con
@OneToMany
, se cargará perezosamente. Pero, por otro lado, la asociación de libros relacionada con el tema de la colección , anotada con@ManyToOne
, se carga de manera importante (por[default][1]
para@ManyToOne
,fetchType=EAGER
). Podemos cambiar el comportamiento colocando fetchType.EAGER en@OneToMany
Subject.java o fetchType.LAZY@ManyToOne
en Books.java.fuente
Fuente
fuente
Quiero agregar esta nota a lo que "Kyung Hwan Min" dijo anteriormente.
Supongamos que está utilizando Spring Rest con este simple arquitecto:
Y desea devolver algunos datos al front-end, si está utilizando
FetchType.LAZY
, obtendrá una excepción después de devolver los datos al método del controlador ya que la sesión se cierra en el Servicio, por loJSON Mapper Object
que no puede obtener los datos.Hay tres opciones comunes para resolver este problema, depende del diseño, el rendimiento y el desarrollador:
FetchType.EAGER
, para que la sesión siga viva en el método del controlador.FetchType.LAZY
método convertidor para transferir datos desdeEntity
otro objeto de datosDTO
y enviarlo al controlador, por lo que no hay excepción si la sesión se cierra.fuente
Hola, he adjuntado 2 fotos para ayudarte a entender esto.
fuente
@ drop-shadow si está utilizando Hibernate, puede llamar
Hibernate.initialize()
cuando invoque elgetStudents()
método:fuente
Perezoso: recupera las entidades secundarias de forma perezosa, es decir, al momento de recuperar la entidad principal, solo obtiene el proxy (creado por cglib o cualquier otra utilidad) de las entidades secundarias y cuando accede a cualquier propiedad de la entidad secundaria, en realidad es recuperado por hibernación.
EAGER: recupera las entidades secundarias junto con la principal.
Para una mejor comprensión, vaya a la documentación de Jboss o puede usar
hibernate.show_sql=true
su aplicación y verificar las consultas emitidas por la hibernación.fuente