Your reasoning is valid (in general; we can however argue about the specific example of the age
field), but unfortunately there is no straight-forward solution for this. Actually, Hibernate has the concept of fetch profiles, but it is currently very limited (you can override the default fetch plan/strategy only with the join-style fetch profiles).
So, the possible workaround to your issue could be as follows.
1) Move age
to a separate entity and associate the Person
entity with it with a lazy one-to-one relationship:
@Entity
class PersonAge {
private Integer age;
}
@Entity
class Person {
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, optional = false)
@JoinColumn(name = "PERSON_AGE_ID")
private PersonAge personAge;
public Integer getAge() {
return personAge.getAge();
}
public void setAge(Integer age) {
personAge.setAge(age);
}
}
2) Define a fetch profile which overrides the default one:
@FetchProfile(name = "person-with-age", fetchOverrides = {
@FetchProfile.FetchOverride(entity = Person.class, association = "personAge", mode = FetchMode.JOIN)
})
3) Enable this profile for each session in the application:
session.enableFetchProfile("person-with-age");
Depending on the framework you use, there should be an easy hook/interceptor which you will use to enable the profile for each session (transaction) that is craeted. For example, an approach in Spring could be to override AbstractPlatformTransactionManager.doBegin of the transaction manager in use.
This way the personAge
will be eagerly loaded in all the sessions in the application, unless the fetch profile is explicitly disabled.
4) Disable the fetch profile in the session in which you use the desired Criteria query:
session.disableFetchProfile("person-with-age");
This way the default fetch plan/strategy is used (specified in the entity mappings), which is the lazy loading of the PersonAge
.