2.1 opción de búsqueda
Los desarrolladores de Hibernate conocen el problema de cargar entidades secundarias desde hace mucho tiempo. Entonces, lo primero que hicieron fue agregar un parámetro de búsqueda especial a las anotaciones @OneToMany
, @ManyToMany
.
Este parámetro puede tomar dos valores:
- ANSIOSO
- PEREZOSO
Ejemplo:
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
Si el parámetro de obtención es igual a EAGER , cuando se cargue la entidad principal, también se cargarán todas sus entidades secundarias. Además, Hibernate intentará hacerlo en una consulta SQL, generando una consulta considerable y obteniendo todos los datos a la vez.
Si el parámetro de búsqueda toma el valor LAZY , cuando se cargue la entidad principal, la entidad secundaria no se cargará. En su lugar, se creará un objeto proxy.
Con la ayuda de este objeto proxy, Hibernate rastreará el acceso a esta entidad secundaria y la cargará en la memoria la primera vez que se acceda.
Si recordamos nuestra situación con comentarios:
@Entity
@Table(name="user")
class User {
@Column(name="id")
public Integer id;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
public List<Comment> comments;
}
Entonces tienes una "elección elegante":
Si fetch = FetchType.EAGER
, entonces Hibernate cargará todos los comentarios en la primera línea de código:
User user = session.get(User.class, 1); //load all comments here
List<Comment> comments = user.getComments();
Si fetch = FetchType.LAZY
, entonces Hibernate cargará todos los comentarios en la segunda línea de código:
User user = session.get(User.class, 1);
List<Comment> comments = user.getComments(); //load all comments here
Como ya puedes adivinar, no tienes opción cuando no carga todos los comentarios :)
2.2 Valor por defecto
Si no especifica una opción de recuperación para la @ManyTo
anotación ..., Hibernate utilizará los valores predeterminados.
Son ligeramente diferentes para diferentes tipos de anotaciones. Para las anotaciones @OneToOne
y @ManyToOne
es ENAMORADO, para las anotaciones @OneToMany
y @ManyToMany
es PEREZOSO. Es fácil de recordar: si nos referimos a un objeto, se cargará por completo. Si nos referimos a una colección, entonces se cargará la primera vez que se acceda a ella.
2.3 Anotación @LazyCollection
Como ya has visto, el parámetro fetch no ayuda mucho cuando se trabaja con colecciones. Los creadores de Hibernate intentaron arreglar esto agregando una anotación especial @LazyCollection
. Suele escribirse así:
@LazyCollection(LazyCollectionOption.TRUE)
Debe especificarlo al mapear campos de colección:
@Entity
@Table(name="user")
class User {
@Column(name="id")
public Integer id;
@OneToMany(cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.TRUE)
public List<Comment> comments;
}
Esta anotación tiene un parámetro de valor que puede tomar uno de tres valores:
- LazyCollectionOption. VERDADERO
- LazyCollectionOption. FALSO
- LazyCollectionOption. EXTRA
Las dos primeras opciones son muy similares a la opción de búsqueda.
Si el parámetro se establece en LazyCollectionOption.TRUE
, significa que los valores del campo de comentarios no se cargarán desde la base de datos cuando se cargue el objeto Usuario principal. Los objetos de tipo Comentario se cargarán la primera vez que se acceda al campo de comentarios. De hecho, este es el equivalente del parámetroFetchType.LAZY
Si el parámetro se establece en LazyCollectionOption.FALSE
, significa que los valores del campo de comentarios se cargarán desde la base de datos en el momento de cargar el objeto Usuario principal. Los objetos de tipo Comentario se cargarán la primera vez que se acceda al campo de comentarios. De hecho, este es el equivalente del FetchType.EAGER
.