I have a set of simple models like this (getters and setters omitted for brevity):
@Entity
public class Customer {
@Id
private Integer id;
}
@Entity
public class Order {
@Id
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customer_id")
private Customer customer;
}
I am trying to load an Order using a Spring JPA repository with a findById method, including the customer.
First I tried this:
@Transactional
Optional<Order> findById(Integer id) {
return repository.findById(id);
}
But when I tried to access Customer I got a LazyInitializationException: could not initialize proxy - no Session. So after referring to some other questions, I updated my method to be a bit uglier, but to explicitly call Hibernate.initialize
:
@Transactional
Optional<Order> findById(Integer id) {
return repository.findById(id)
.map( order -> {
Hibernate.initialize(order.getCustomer());
return order;
);
}
But I still get org.hibernate.LazyInitializationException: could not initialize proxy - no Session
. repository
is a regular CrudRepository which provides the findById
method out-of-the-box.
How can I initialize this lazily loaded child entity? My understanding is that the @Transactional
indicates that I should still be within the transaction for the entirety of this method call. The only thing further downstream is the repository itself, which is just an interface, so I'm not sure how else to go about forcing the load of this child entity.
The Order entity and everything else in it is retrieved properly from the database; it's only when I try to get the lazy-loaded child entities that we start having issues.
The only way I managed to get this working was to write a custom hql method in the Repository using a left join fetch
. While that works, it clutters up my repository with a method that is pretty much a duplicate of another and which I'm pretty sure I'm not actually supposed to need (so I would rather not do it this way.)
Spring-Boot 2.1.4.RELEASE, Spring 5.1.6.RELEASE, Hibernate 5.3.7.Final.