简体   繁体   中英

Hibernate @Async future results and Lazy initialization exception

I have controller method with some services methods, I want to use them paralllel.

Controller method

public String (...) {
    Future<List<Obj1>> obj1Result= asyncDelegate.getAllObj1();
    Future<List<Obj2>> obj2Result= asyncDelegate.getAllObj2();
    Future<List<Obj3>> obj3Result= asyncDelegate.getAllObj3();

    while(!(obj1Result.isDone() && obj2Result.isDone() && obj3Result.isDone())) {
        Thread.sleep(10);
    }
    model.addAttribute(...);
    return "view";
}

Also I have delegate service with @Async marked methods which returns future results from @Transactional services

@Component
public class AsyncDelegate {

Logger logger = Logger.getLogger(getClass());

@Async
public Future<List<Obj1>> getAllObj1() {
    return new AsyncResult<List<Obj1>>(obj1Service.getAll());
}

@Async
public Future<List<Obj2>> getAllObj2() {
    return new AsyncResult<List<Obj2>>(obj2Service.getAll());
}

@Async
public Future<List<Obj3>> getAllObj3() {
    return new AsyncResult<List<Obj3>>(obj3Service.getAll());
}

}

Obj1, Obj2, Obj2 have lazy initialized collections, to load them in view I use

<filter>
    <filter-name>openSessionInView</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
     <async-supported>true</async-supported>
</filter>

Finally in generate view I'm getting

 ERROR org.hibernate.LazyInitializationException:42 - failed to lazily initialize a collection of role: obj.lazy-collection, no session or session was closed

How to solve this problem ?

Your problem is that Spring is running with all the hibernate configuration in the ThreadLocal, and you´re creating new threads with his own thread local where Hibernate session does not exist.

So you will need to initialize the session for those entities if they were already created in the previous thread, otherwise hibernate cannot initialize those hibernate proxy entities since the session does not exist.

You could explicitly initialize proxies when you are sure that they will be used out of the session in which they are loaded:

Hibernate.initialize(obj.getLazyCollection());

You invoke this in the same transaction in which you load obj .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM