0

I have a one-to-many collection with lazy="extra" attribute.

Class Foo {
   List<Bar> barList;
}

I have a class with lazy="false" initialization which contains mentioned class collection.

Class FooContainer {
   List<Foo> fooList;
}

I get FooContainer entity with service, so I will need to use .size() out of transaction;

FooContainer fc = serviceImpl.getFCById(fooContainerId);

This way fc.getFooList() is initialized. Then I need to get only the size of barList. I do not need to fetch whole collection.

for(Foo currentItem: fc.getFooList()) {
   int barSize = currentItem.getBarList().size();
}

This is when LazyInitializationException appears. I tried to call this method.

@Transactional
Class AnotherServiceImpl {
   int getBarListSize(Foo foo){ 
      return foo.getBarList().size();
   }
}

But it didn't work because there is no session. I can do getHibernateTemplate().getCurrentSession.initialize(foo.getBarList()) in AnotherServiceImpl and this will work, but I probably will fetch all items, which is unacceptable.

Is there a way to get collection size without fetching?

Nalmelune
  • 78
  • 2
  • 10
  • Related: https://stackoverflow.com/questions/2198528/hibernate-hql-get-count-of-results-without-actually-returning-them – Salem Nov 29 '17 at 18:16
  • 1
    I suspect it's a problem of entities being managed or not. You should add what Transaction-Propagation is used to create FooContainer and of the getBarListSize-calling method. – aschoerk Nov 29 '17 at 18:18
  • @aschoerk `ServiceImpl` and `AnotherServiceImpl` has default propagation here. Method where I get `FooContainer fc` and call `.size()` is the same method and it is not `@Transactional`. – Nalmelune Nov 29 '17 at 18:32

1 Answers1

1

Together with the comment Method where I get FooContainer fc and call .size() is the same method and it is not @Transactional:

The entities get unmanaged when FooContainer is returned because of the committed transaction and therefore the "extra"-lazy collection cannot get resolved. It would work if the calling method was Transactional as well.

You have the following options I see, you can:

  1. make the calling method also Transactional with default propagation
  2. or merge foo into the hibernate session valid in getBarListSize to make it managed again.
  3. or make barList in Foo also Lazy(false) then everything is fetched during loading of FooContainer. (but that seems not to be acceptable)
  4. or get the sizes using a group by statement.
aschoerk
  • 3,333
  • 2
  • 15
  • 29