This forum is now a read-only archive. All commenting, posting, registration services have been turned off. Those needing community support and/or wanting to ask questions should refer to the Tag/Forum map, and to http://spring.io/questions for a curated list of stackoverflow tags that Pivotal engineers, and the community, monitor.

scheduling a DAO operation in hibernate

Aug 7th, 2007, 02:24 PM

i'm trying to schedule a call to a method within a class that performs a DAO operation, im using the java.util.Timer and java.util.TimerTask classes
unfortunately, im getting the LazyInitializationException, which i assume is caused because theres no open session when im trying to perform the DAO operation?
to fix it i tried to create a session using SessionFactoryUtils, and retrieving the session from my DAO object, but im still getting the LIE, my code is as follows

For nearly sure the session stuff (as well as possible transaction handling) relies on ThreadLocals - which you obviously break with your timer. If that's not a problem (creating a new session in the timer thread) you probably use an entity which is attached to the session in the original thread, but not to the timer thread. You have to reattach it to the session in the timer thread - what ever this causes for side-effects in the original thread/ session.

This all sounds like a major pain. Must it be a different thread? And if so, you should not do this inside the DAO but on the service level.

Joerg

Comment

that method sits within the class that the dao instanciates, mod is a final copy of the object that its within, and the train method takes hours to complete, but only talks to the database once at the beginning and once at the end, so it must be done in a seperate thread

here is what i have now, ive gotten it so that it can read the data from the database at a later date, still using the lazy associations in the mapping, so its generating the object graph, but it wont save, when it tries to save (the blob object does not exist) i get an illegalStateException error, and when i try to update it (the blob object exists but needs to be updated) it doesnt error out, but also doesnt update the database

Comment

thanks for all the help, i implemented your method with the executor, and im still getting the illegalStateException error, but only when i try to save, when it reads the values it reads them in fine and correctly

Then use the Spring task executor stuff to fire it off, that way all the transaction and hibernate session stuff will be taken care of, because the code doing the thing is actually wrapped in the Spring transactional proxy.

It is a little bit more work (a new interface and class), but I think it is worth it....unit testing the FileReader is now easy etc.

Does that make sense? Treat the file reading service just like any other service. The fact you want to execute it asynchronously is neither here nor there.

So to actually fire off the job, you have a number of approaches, the important thing is that you ask Spring for the ModelTrainerFileReader, to give it a chance to create the TX and hibernate session.

Comment

sorry to be a bother
but, i think ive almost got it, im getting a lazyInitializationException now, im assuming that means it didnt open a session, so the transactional annotation didnt do what i thought it would,

if im getting a LIE now, do i have to create a session from a session factory in the model trainers train() method?
you said that if spring loaded it it would take care of that, so im thinking im missing something

Comment

ok, so heres my new problem, the application context i pass in is the one at the current time (i implemented ApplicationContextAware in one of the classes and pass the context along)

ctx.getBean("ModelTrainer"); returns a model trainer, but im still getting the LIE, is this because im using the application context from 10 seconds ago? if so, how can i possibly get the current running application context in a run method of a threadable class

Code:

public void run()
{
try
{
//ctx is the context from when the timer was set, not now when it runs
trainer=(ModelTrainer)ctx.getBean("ModelTrainer");
trainer.setModelUID(modelUID);
trainer.train();
}
catch(Exception ex)
{
System.out.println("Cause: "+ex.getCause());
ex.printStackTrace();
}
}

if i understand correctly, the only way to get the context in a class is to have that class be applicationContextAware and have it be instanciated by spring, and i have no idea how to instanciate a runnable class by spring,
so im asking, is that doable, or is there some other method of doing this i should go about