Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy loading works, but shouldn't

The context of this question is within spring-boot, using spring-data-jpa and hibernate.

A colleague wrote an @Service and annotated the service method with @Transactional. The service method loads an entity, and subsequently hits a one-to-many lazily loaded collection (fetch = FetchType.LAZY). The service method is invoked by some custom delegator, which i will come back to. This works fine when invoked from a @RestController endpoint.

When i invoked the service from a camel route (again via the custom delegator) it barfed with a lazy initialization exception.

On digging, found that the service implements an interface, the custom delegator looks up the service (it is injected so has proper proxy) and calls a method on the interface which is actually a java-8 default method. This default-method then locally calls the @Transactional method.

So there's the problem :- this is a LOCAL method call so the aspecting/proxy-ing of the @Transactional annotation is not done (we use aspectJAutoProxy) so the method is NOT invoked within a transaction, so the lazy-loading SHOULD fail. And to double-check, also tried it via an @Scheduled annotation: same behaviour. Barfs like it should.

My Question: So why does it work when called from the @RestController? This is driving me nuts!

There is no transactional annotation on the rest controller endpoint.

I added some debug code to the service using TransactionSynchronizationManager.isActualTransactionActive() and it shows that in no case is there a transaction, even when being called via the controller endpoint.

So why does the lazy loading work when being called from the controller? I dumped all SQL and at no points are the lazy-collection already loaded, so they are not in any hibernate cache.

I remember reading once that lazy loading was a hint, not a command, but still... why does it work in that one case?

like image 881
Richard Avatar asked Dec 30 '25 14:12

Richard


1 Answers

When your method annotate to transactional hibernate session close after return method , if object that return from method have lazy , lazy property not load and you get exception that session close. You can use fetch in query or using OSIV

like image 167
ali akbar azizkhani Avatar answered Jan 01 '26 23:01

ali akbar azizkhani