cp.
cp.

Reputation: 1271

org.hibernate.LazyInitializationException in @PostConstruct

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();
            }
        });
    }
}

Upvotes: 0

Views: 1077

Answers (1)

Yuriy Tsarkov
Yuriy Tsarkov

Reputation: 2548

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

Upvotes: 1

Related Questions