Issue
I have an SpringBootApp with embedded Derby;works fine. When I implement CommandLineRunner or @PostConstruct I get above error
"org.hibernate.LazyInitializationException failed to lazily initialize a collection of role:...- could not initialize proxy - no Session".
How do I create a session with Hibernate before the app actually runs but after the applications.properties file has been loaded? Also what is SprinBoot doing elsewhere that prevents this error in normal running?
@Component
@Transactional
public class DatabaseTesting01 {
private static Logger logger = LoggerFactory.getLogger(DatabaseTesting01.class);
@Autowired
EDITypeService ediTypeService;
@Autowired
VendorService vendorService;
@Autowired
SubscriberService subscriberService;
@PostConstruct
public void init(){
Vendor v = vendorService.findOneByShortName("UNFI");
logger.debug("Vendor:UNFI"+v.toString());
}
}
UPDATE This is what worked.HTH.
@Component
@Service("database01")
public class Database01 {
private static Logger logger = LoggerFactory.getLogger(Database01.class);
@Autowired
@Qualifier("transactionManager")
protected PlatformTransactionManager txManager;
@Autowired VendorService vendorService;
@PostConstruct
private void init(){
TransactionTemplate tmpl = new TransactionTemplate(txManager);
tmpl.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
vendorService.deleteAll();
}
});
}
}
Solution
The only thing the @Transactional
does over the class is applying transactional functionality (creating proxy, etc) to all public methods. So you should not rely on the initialization code such as @PostConstruct
.
Here is the appropriate spring reference
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation (in effect, a method within the target object calling another method of the target object) does not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional. Also, the proxy must be fully initialized to provide the expected behavior, so you should not rely on this feature in your initialization code (that is, @PostConstruct).
UPD
In your case the main problem is a loading of a one-to-many list of roles of the vendor. And it is a predictable behaviour because of the transaction absence. I hope this topic will help you to workaround a problem, but anyway just ask yourself - is it really necessary to do such a things in a @PostCunstruct
? If not, you can just implement an alternative method in the repository, using projections or a jpql constructor to get rid of joined entities loading
Answered By - Yuriy Tsarkov