Is there any way to check whether an entity's lazy collection attribute is initialized once we're outside the Transactional session?
For example, my Job entity has a lazy association to a list of Step, which is only sometimes initialized. In my controller, I would like to know if the steps collection has been initialized, although I'm met with a LazyInitializationException instead:
org.hibernate.LazyInitializationException: Unable to perform requested lazy initialization [com.overflow.stack.Job.steps] - no session and settings disallow loading outside the Session
at org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper.throwLazyInitializationException(EnhancementHelper.java:199) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper.performWork(EnhancementHelper.java:89) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor.loadAttribute(LazyAttributeLoadingInterceptor.java:76) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor.fetchAttribute(LazyAttributeLoadingInterceptor.java:72) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor.handleRead(LazyAttributeLoadingInterceptor.java:53) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.bytecode.enhance.spi.interceptor.AbstractInterceptor.readObject(AbstractInterceptor.java:153) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at com.overflow.stack.Job.$$_hibernate_read_steps(Job.java) ~[classes/:?]
at com.overflow.stack.Job.getSteps(Job.java:135) ~[classes/:?]
...
@Entity
public class Step {
...
}
@Entity
public class Job {
@OneToMany(mappedBy = "job", fetch = FetchType.LAZY)
private List<Step> steps = new ArrayList<>();
public List<Step> getSteps() {
return steps;
}
...
}
@Controller
public JobController {
public List<Step> getJobSteps(Long id) {
// Transactional service class method which fetches by id (does not initialize steps)
Job job = jobService.getJob(id);
if (Hibernate.isInitialized(job.getSteps())) { // Throws LazyInitializationException
return job.getSteps();
} else {
return List.of();
}
}
}
@Service
@Transactional
public JobService {
@Autowired JobRepository jobRepo;
public Job getJob(Long id) {
Job job = jobRepo.findById(id).get();
Hibernate.unproxy(job);
return job;
}
}
In this case, the exception is thrown when it attempts to execute job.getSteps() in the if statement.
I know that the session is closed by the time I leave the service call (the controller is not Transactional), although I'm wondering if there's any way to check if it's been initialized, or is the getSteps() method completely out of reach at that point?