2.1 fetch option
The developers of Hibernate have known about the problem with loading child entities for a long time. So the first thing they did was add a special fetch parameter to the annotations @OneToMany
, @ManyToMany
.
This parameter can take two values:
- EAGER
- LAZY
Example:
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
If the fetch parameter is equal to EAGER , then when the parent entity is loaded, all its child entities will also be loaded. Also, Hibernate will try to do it in one SQL query, generating a hefty query and fetching all the data at once.
If the fetch parameter takes the value LAZY , then when the parent entity is loaded, the child entity will not be loaded. Instead, a proxy object will be created.
With the help of this proxy object, Hibernate will track the access to this child entity and load it into memory the first time it is accessed.
If we recall our situation with comments:
@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;
}
Then you have a “chic choice”:
If fetch = FetchType.EAGER
, then Hibernate will load all comments on the 1st line of code:
User user = session.get(User.class, 1); //load all comments here
List<Comment> comments = user.getComments();
If fetch = FetchType.LAZY
, then Hibernate will load all the comments on the 2nd line of code:
User user = session.get(User.class, 1);
List<Comment> comments = user.getComments(); //load all comments here
As you can already guess, you have no option when it does not load all the comments :)
2.2 Default value
If you don't specify a fetch option for the @ManyTo
... annotation, then Hibernate will use the default values.
They are slightly different for different annotation types. For annotations @OneToOne
and @ManyToOne
is EAGER, for annotations @OneToMany
and @ManyToMany
is LAZY. It's easy to remember - if we refer to one object, then it will be loaded completely. If we refer to a collection, then it will be loaded the first time it is accessed.
2.3 @LazyCollection annotation
As you have already seen, the fetch parameter does not help much when working with collections. The creators of Hibernate tried to fix this by adding a special annotation @LazyCollection
. It is usually written like this:
@LazyCollection(LazyCollectionOption.TRUE)
You need to specify it when mapping collection fields:
@Entity
@Table(name="user")
class User {
@Column(name="id")
public Integer id;
@OneToMany(cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.TRUE)
public List<Comment> comments;
}
This annotation has a value parameter that can take one of three values:
- LazyCollectionOption. TRUE
- LazyCollectionOption. FALSE
- LazyCollectionOption. EXTRA
The first two options are very similar to the fetch option.
If the parameter is set to LazyCollectionOption.TRUE
, it means that the values of the comments field will not be loaded from the database when the parent User object is loaded. Objects of type Comment will be loaded the first time the comments field is accessed. In fact, this is the equivalent of the parameterFetchType.LAZY
If the parameter is set to LazyCollectionOption.FALSE
, it means that the values of the comments field will be loaded from the database at the time of loading the parent User object. Objects of type Comment will be loaded the first time the comments field is accessed. In fact, this is the equivalent of the FetchType.EAGER
.
GO TO FULL VERSION