java - fetchtype - lazy hibernate example
¿Qué es la carga diferida en Hibernate? (15)
¿Qué es la carga diferida en Java? No entiendo el proceso. ¿Alguien puede ayudarme a entender el proceso de carga lenta?
La carga diferida es un patrón de diseño comúnmente utilizado en la programación de computadoras para diferir la inicialización de un objeto hasta el punto en que se necesita. Puede contribuir a la eficiencia en el funcionamiento del programa si se utiliza de forma adecuada y adecuada
Wikipedia
Enlace de carga lenta desde hibernate.org
"Carga diferida" significa que una entidad se cargará solo cuando realmente acceda a la entidad por primera vez.
El pattern es así:
public Entity getEntity() {
if (entity == null) {
entity = loadEntity();
}
return entity;
}
Esto ahorra el costo de precargar / prellenar todas las entidades en un gran conjunto de datos de antemano, mientras que, después de todo, en realidad no las necesita todas .
En Hibernate, puede configurar para cargar de forma perezosa una colección de entidades secundarias. La carga diferida real se realiza dentro de los métodos de PersistentSet
que Hibernate usa "debajo de las capuchas" para asignar la colección de entidades como Set
.
P.ej
public class Parent {
private Set<Child> children;
public Set<Child> getChildren() {
return children;
}
}
.
public void doSomething() {
Set<Child> children = parent.getChildren(); // Still contains nothing.
// Whenever you call one of the following (indirectly),
// Hibernate will start to actually load and fill the set.
children.size();
children.iterator();
}
¿Carga lenta? Bueno, simplemente significa que los registros secundarios no se extraen de inmediato, sino automáticamente tan pronto como intenta acceder a ellos.
Bueno, simplemente significa cargar los datos que necesita actualmente en lugar de cargar todo el conjunto de datos a la vez que no usará ahora. De este modo, la carga de la aplicación es más rápida de lo normal.
En lenguaje sencillo, es como si estuvieras haciendo un pastel y necesitarás de 5 a 10 ingredientes del refrigerador. Tienes dos opciones para obtener todos los ingredientes del refrigerador y ponerlos en la plataforma de la cocina o traer el artículo que quieras cuando lo necesites. De manera similar, en la carga ansiosa puedes buscar toda la información sobre bean y sus clases relacionadas (no hijo o es una relación pero tiene una relación, es decir, el pastel tiene harina, tiene leche, tiene crema, etc.) y en el caso de la carga diferida primero traes solo su identificador y los valores que provienen de la misma mesa (ingredientes necesarios que primero necesitarás en tu tazón en caso de torta) ... toda la información que proviene de otras tablas será recuperada cuando sea necesario / usado.
Espero que esto ayude :)
Hiberante admite la función de inicialización lenta para entidades y colecciones. El motor de Hibernate solo carga aquellos objetos que estamos consultando no otras entidades o colecciones.
lazy = "false" de forma predeterminada cargar la mención de inicialización para el único elemento secundario es lazy.in en caso de verdadero que el padre está cargando no es compatible con child
La carga diferida le permite diferir la recuperación de la asociación o tener un mejor control sobre la estrategia de búsqueda.
Cuando utiliza la carga EAGER, define un plan de búsqueda global que no puede anularse en el momento de la consulta, lo que significa que está limitado a una decisión que tomó al diseñar su modelo de entidad. La búsqueda de EAGER es un olor a código , porque la estrategia de búsqueda es una política de tiempo de consulta y puede diferir de un caso de uso empresarial a otro.
La estrategia de búsqueda es un aspecto muy importante, ya que demasiada búsqueda de EAGER puede causar problemas graves relacionados con el rendimiento.
La inicialización lenta es una optimización del rendimiento. Se usa cuando los datos se consideran ''caros'' por alguna razón. Por ejemplo: si el llamador puede realmente no necesitar el valor hashCode para un objeto, siempre se puede considerar innecesario el cálculo del hashCode para todas las instancias del objeto. ya que el acceso a un sistema de archivos o red es relativamente lento, tales operaciones deben posponerse hasta que sean absolutamente necesarias.
La inicialización diferida tiene dos objetivos: retrasar una operación costosa hasta que sea absolutamente necesario almacenar el resultado de esa costosa operación, de modo que no tenga que volver a repetirla
La recuperación diferida decide si cargar objetos secundarios mientras se carga el objeto principal. Debe hacer esto configurando el archivo de mapeo de hibernación respectivo de la clase padre. Lazy = true
(significa no cargar el elemento secundario) De forma predeterminada, la carga diferida de los objetos secundarios es verdadera.
Esto asegura que los objetos secundarios no se cargan a menos que se invoquen explícitamente en la aplicación llamando al método getChild()
en el padre. En este caso, hibernate emite una nueva llamada a la base de datos para cargar al hijo cuando getChild()
se llama objeto.
Pero en algunos casos, es necesario cargar los objetos secundarios cuando se carga el padre. Simplemente haga que lazy = false e hibernate cargue el elemento secundario cuando el padre se carga desde la base de datos.
Ejemplo: si tienes una TABLA? EMPLEADO asignado al objeto Empleado y contiene un conjunto de objetos de Dirección. Clase de padres: clase de empleado, clase de niños: clase de dirección
public class Employee {
private Set address = new HashSet(); // contains set of child Address objects
public Set getAddress () {
return address;
}
public void setAddresss(Set address) {
this. address = address;
}
}
En el archivo Employee.hbm.xml
<set name="address" inverse="true" cascade="delete" lazy="false">
<key column="a_id" />
<one-to-many class="beans Address"/>
</set>
En la configuración anterior. If lazy="false"
: cuando carga el objeto Employee, también se carga la dirección child object object y se establece en el método setAddresss (). Si llama a employee.getAdress (), entonces se devuelven datos cargados. No se realiza ninguna nueva llamada a la base de datos.
If lazy="true"
: - Esta es la configuración predeterminada. Si no lo menciona, hibernate considere lazy = true. cuando carga el objeto Employee, esa vez no se carga la dirección del objeto hijo. Necesita una llamada adicional a la base de datos para obtener objetos de dirección. Si llama a employee.getAdress()
, esa consulta de base de datos de tiempo se activa y devuelve resultados. Nueva llamada a la base de datos.
Lazy establece si se cargan objetos secundarios mientras se carga el objeto primario. Debes hacer esta configuración, respetando el archivo de mapeo de hibernación de la clase padre. Lazy = true (significa no cargar el elemento secundario) De forma predeterminada, la carga diferida de los objetos secundarios es verdadera . Esto asegura que los objetos secundarios no se cargan a menos que se invoquen explícitamente en la aplicación llamando al método getChild () en el padre. En este caso, hibernate emite una nueva llamada a la base de datos para cargar al hijo cuando getChild () se llama objeto. Pero en algunos casos, sí es necesario cargar los objetos secundarios cuando se carga el padre. Simplemente haga que lazy = false e hibernate cargue el elemento secundario cuando parent se cargue desde la base de datos.Exampleslazy = true (predeterminado) La dirección secundaria de la clase User se puede volver floja si no se requiere con frecuencia.lazy = falsePuede que necesite cargar el objeto Author para Book parent cada vez que maneja el libro para la librería en línea.
Lazy establece si se cargan objetos secundarios mientras se carga el objeto primario. Debes hacer esta configuración, respetando el archivo de mapeo de hibernación de la clase padre. Lazy = true (significa no cargar el elemento secundario) De forma predeterminada, la carga diferida de los objetos secundarios es verdadera .
Martin Fowler define el patrón Lazy Load en Patterns of Enterprise Application Architecture como tal:
Un objeto que no contiene todos los datos que necesita pero sabe cómo obtenerlo.
Por lo tanto, al cargar un objeto determinado, la idea es no cargar los objetos relacionados que no puede usar de inmediato para ahorrar el costo de rendimiento relacionado. En cambio, los objetos relacionados se cargarán solo cuando se usen.
Este no es un patrón específico para el acceso a datos e Hibernate, pero es particularmente útil en tales campos e Hibernate admite la carga diferida de asociaciones de uno a muchos y asociaciones de un solo punto (uno a uno y muchos a uno) también bajo ciertas condiciones. La interacción lenta se analiza con más detalle en el Capítulo 19 de la Documentación de referencia de Hibernate 3.0.
Por defecto, la carga diferida es verdadera. La carga lenta significa que cuando se ejecuta la consulta de selección no golpea la base de datos. Esperará la función getter, es decir, cuando lo solicitemos, se obtendrá de la base de datos. por ejemplo: usted es un padre que tiene un niño con muchos juguetes. Pero el problema actual es cada vez que lo llamas (asumimos que tienes un niño), él viene a ti con todos sus juguetes también. Ahora este es un problema ya que no quieres que lleve sus juguetes todo el tiempo. Entonces, siendo el padre racional, usted sigue adelante y define los juguetes del niño como PEREZOSOS. Ahora cada vez que lo llamas, él viene a ti sin sus juguetes.
Sorprendentemente, ninguna de las respuestas habla de cómo se logra por hibernación detrás de las pantallas.
La carga diferida es un patrón de diseño que se utiliza de manera efectiva en la hibernación por motivos de rendimiento, lo que implica las siguientes técnicas.
1. Instrumentación del código de bytes :
Mejora la definición de la clase base con los hooks hibernación para interceptar todas las llamadas a ese objeto de entidad.
Hecho en tiempo de compilación o ejecute [carga] tiempo
1.1 Tiempo de compilación
Operación de tiempo de compilación posterior
Sobre todo por plugins maven / ant
1.2 tiempo de ejecución
- Si no se realiza la instrumentación en tiempo de compilación, esto se crea en tiempo de ejecución usando bibliotecas como javassist
El objeto de entidad que Hibernate devuelve es proxy del tipo real.
Ver también: Javassist. ¿Cuál es la idea principal y dónde el uso real?
Supongamos que tiene un padre y ese padre tiene una colección de hijos. Hibernate ahora puede "cargar de forma diferida" a los niños, lo que significa que en realidad no carga a todos los niños cuando carga el elemento primario. En cambio, los carga cuando se les solicita hacerlo. Puede solicitar esto explícitamente o, y esto es mucho más común, que hibernate los cargará automáticamente cuando intente acceder a un elemento secundario.
La carga diferida puede ayudar a mejorar el rendimiento de manera significativa, ya que a menudo no necesitará los niños para que no se carguen.
También ten cuidado con el problema n + 1. De hecho, Hibernate no cargará a todos los niños cuando acceda a la colección. En cambio, cargará a cada niño individualmente. Al iterar sobre la colección, esto causa una consulta para cada niño. Para evitar esto, puede hacer que hibernate intente cargar todos los hijos simultáneamente, por ejemplo, llamando a parent.getChildren (). Size ().