0

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

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. However how do I configure a CommandLineRunner or @PostConstruct to properly configure for database service use? I was using zetcode.com/springboot/commandlinerunner. Also where in SpringBoot does it configure properly? To just better understand architeture.
Thank you, your first reference in your above clarification worked. I updated my original for future searchers. This is "good" what is "better" or "best"? This is only for testing. Should I populate the db as a separate test run or like this and just comment out the @Component?
In general you can easily remove the @Component because instantiation is already provided within the @Service implementation, however the best way is to use integration tests for a test purposes

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.