Card 02/ 07
All 7 cards
GotchaDifficulty: Advanced1 min
The Collection That Only Loads Inside a Transaction
A @OneToMany collection loads fine, right up until it's touched from outside the transaction that fetched its owner — which can be as simple as one repository call finishing before your code gets around to reading the collection.
void accessRidesOutsideTransaction(Long id) {
RiderEntity rider = repo.findById(id).orElseThrow();
// repo.findById()'s own transaction already closed by the time execution gets here
System.out.println(rider.rides.size());
}OUTSIDE transaction -> LazyInitializationException: failed to lazily initialize a collection of role: rides.RiderEntity.rides: could not initialize proxy - no SessionA repository method carries its own short transaction by default — that's how findById runs at all without one wrapping the whole method. rider.rides is a lazy proxy, not real data yet, and by the time .size() is called, the transaction that could have filled it in is already gone. This is Spring Data JPA's failure mode specifically: Spring Data JDBC has no lazy loading to fail, because it never leaves anything unloaded in the first place — an aggregate loads in full, every time.