Zubaidullo's Blog
Inside Guice transaction session, when Object is loaded it's LAZY loading joined Objects are loaded once inside that session context. So, when transaction is rolled back LAZY loaded objects will be lost.
We can think this case: void distributeSMS( List<User> users ) { for ( User user: users ) { for ( Phone phone: user.getPhones() ) //here getPhones are Lazy loaded { try { sendSMS( phone ); } catch( Exception e ) { log.error( e.getMessage() ); } } } } @Transactional void sendSMS( Phone phone ) { //here some SMS sending operations } In this example we see that, user's phone numbers are Lazy loaded and given to transaction. In RuntimeException case, sentSMS() method will be rolled back and catches inside sendSMSToAll(). In normal view, we see that it throws exception for one Phone and it should continue next job. But! Here we will see Exception : org.hibernate.LazyInitializationException: could not initialize proxy - no Session Here we can clearly understand how Guice transaction works with Lazy loading. Reason why we get above exception, because Transaction is rolled back and that session is closed. So, in next loop when tries to load user.getPhone() it will throw exception. Here we can use multiple solutions by changing joins or on JPA level. Let's see quicker way to solve above problem and understand well how transaction session works with Lazy load. Before looping user phone numbers, we can just get list of Phones without lazy load. Ex: List<Phone> phones = getUserPhones( user ); ......continue for loop. We get phone numbers with other session and in transaction roll back case this session will be alive.
Click to set custom HTML
0 Comments
|
AuthorJava developer and experienced Designer, Flash animator. Very good algorithmic programming skills. Participant of International Olympiads. Very good skilled in designing. Archives
September 2017
Categories |