0

My code has several JPA repository method call. I fetch data and aggregate it. But I want to do that in an asynchronous way. So, I am trying to use CompletableFeature. But I am getting the below error:

failed to lazily initialize a collection of X: package_name.CollectionName, could not initialize proxy - no Session

My code: public CompletableFuture aggregateDownloadableData(params...) {

return CompletableFuture.supplyAsync(() -> {
     //my code to manipulate data sets here
     //
     //
    return Boolean.TRUE; 
  }
});

This code works fine if I remove CompletableFeature usage from this method, but not using this.

I also tried providing my own ExecutorService:

 public CompletableFuture<Boolean> aggregateDownloadableData(params...) {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    return CompletableFuture.supplyAsync(() -> {
             //my code to manipulate data sets here
             //
             //
            return Boolean.TRUE; 
          }
        }, executor);
    }

But this doesn't work either.

Any suggestion, please?
N.B: I don't want to load eagerly

user404
  • 1,934
  • 1
  • 16
  • 32

2 Answers2

0

The reason for this exception is that, when run asynchronously, the Hibernate session will be closed before the lazy loaded collection can be initialized. Hence no Session message.

There are several solutions you can try:

  1. Add @Transactional annotation to the code you are calling asynchronously.
  2. Preload the collection before starting a new thread.
  3. Configure the relationship to EAGER. (Just for the record as you don't want it)
Mar-Z
  • 2,660
  • 2
  • 4
  • 16
0

All lazy-loaded associations should be initialized before the data manipulation. The exception appears when you try to access uninitialized data outside Hibernate Session because the data can no longer be fetched from a database.

By not wanting to load associations eagerly, you probably don't want to configure the FetchType.EAGER fetching strategy for the associated entities. Thus, I suggest you use @EntityGraph which allows customization of the fetch-graph for repository methods.

For example, let's assume there is a GroupInfo entity containing a lazy-loaded collection named members. To fetch members eagerly the following method can be added to the repository:

@EntityGraph(attributePaths = { "members" })
GroupInfo getByGroupName(String name);

The method fetches the GroupInfo entity and its members at the same time when the method getByGroupName is called, otherwise members are loaded lazily. This approach avoids the N+1 query issue, resulting in improved performance.

There are also other solutions like Hibernate.initialize() and JOIN FETCH, refer to the question.

Toni
  • 3,296
  • 2
  • 13
  • 34