How to get around a LazyInitializationException in scheduled tasks?

I am working on a J2EE server application that is deployed to Tomcat. I am using Spring as an MVC framework and Hibernate as an ORM provider. My object model has many Lazy relationships (dependent objects are selected on request). A high-level design is similar to service-level methods that invoke several DAO methods to perform database operations. The service method is called either from the Flex user interface or as a scheduled task. When it is called from the Flex interface, the service method works fine, that is, it retrieves some objects using DAO methods and even Lazy boot. This is possible using the OpenSessionInViewFilter configured using the UI servlet.

But when the same service method is called as a scheduled task, it throws a LazyInitializationException. I cannot configure OpenSessionInViewFilter because the servlet or user interface is not associated with it.

I tried to set up a transaction around the scheduled task method so that the service method started the transaction and all DAO methods participated in the same transaction, hoping that the transaction would remain active and the hibernation session would be available. But that does not work.

Please suggest anyone ever get such a configuration. If necessary, I can publish the Hibernate configuration and log messages.

Many thanks for the help!

Shreerang

+4
source share
3 answers

Finally, I was able to fix my problem after some reading in the Spring transaction reference material. I used to try to write a dotted expression to run a scheduled jon inside a transaction. But point-cut used OR (||), and somehow it didn't take my method when it started execution. Consequently, the Transaction never opened. (I already have a workpoint expression for my DAO methods, and I tried to add my planned method to this snapshot.)

Then I found a way to programmatically open a transaction that fixed my problem. In the interest of others, here is a snippet of code:

transactionTemplate.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus status) { // Invoke the real method inside transaction context doWork(); } }); 

For more information on TransactionTemplate see Spring's source documentation here: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-programmatic

+3
source

The code inside OpenSessionInViewFilter not complicated, I have had success in changing the source to fit my own needs, all he really needs is a thread in which lazy loading will be performed.

I also used Quartz for a lot of scheduled tasks, it works very well with container-driven transactions. The trick I resorted to several times to ensure that lazy collections load before the code exits the transactional boundary, you need to create a dedicated method in which I call the necessary methods:

 @Transactional private SomeOobj getSomeObj(Long id) { SomeObj o = someObjDao.find(id); o.getLazyCollection().size(); // <- load the collection return o; } 

In these cases, it would be better if the necessary data was loaded with impatience when the object was loaded for the first time, but I know that this is not always an option. Good luck.

+1
source

OpenSessionInViewFilter is a bit of a hack, it's not good to rely on it too much.

The best common solution is to record your sleep requests so that data is retrieved impatiently, not lazily. This means using fetch join .

If this is not possible or practical, your scheduled task can do all the work inside the transaction . This should keep the session open until it ends.

0
source

Source: https://habr.com/ru/post/1312135/


All Articles