Hibernate Criteria FetchMode.JOIN is doing lazy loading

Viewed 155

I have a paginated endpoint which internally uses Hibernate Criteria to fetch certain objects and relations. The FetchMode is set as FetchMode.JOIN. When I am trying to hit the endpoint, the request seems to work fine for few pages but is then erring out with :

could not initialize proxy - no Session

Method is as as below:

@Override
public Page<Person> findAllNotDeleted(final Pageable pageable)
{
    final var criteria = createCriteria();
    criteria.add(Restrictions.or(Restrictions.isNull(DELETED), Restrictions.eq(DELETED, false)));

    criteria.setFetchMode(PERSON_RELATION, FetchMode.JOIN);
    criteria.setFetchMode(DEPARTMENT_RELATION, FetchMode.JOIN);

    criteria.setFirstResult((int) pageable.getOffset());
    criteria.setMaxResults(pageable.getPageSize());
    criteria.addOrder(asc("id"));

    final var totalResult = getTotalResult();

    return new PageImpl<>(criteria.list(), pageable, totalResult);
}


private int getTotalResult()
{
    final Criteria countCriteria = createCriteria();
    countCriteria.add(Restrictions.or(Restrictions.isNull(DELETED), Restrictions.eq(DELETED, false)));
    return ((Number) countCriteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();
}

Also, the call to findAllNotDeleted is done from a method anotated with @Transactional.

Not sure what is going wrong. Any help would be highly appreciated.

EDIT I read that FetchMode.Join does not work with Restrictions. So I tried implementing it using CriteriaBuilder but again stuck with the issue.

@Override
public Page<Driver> findAllNotDeleted(final Pageable pageable)
{
    final var session = getCurrentSession();
    final var builder = session.getCriteriaBuilder();
    final var query = builder.createQuery(Person.class);
    final var root = query.from(Driver.class);
    root.join(PERSON_RELATION, JoinType.INNER)
        .join(DEPARTMENT_RELATION,JoinType.INNER);
        
    //flow does not reach here.....
        
    var restrictions_1 = builder.isNull(root.get(DELETED));
    var restrictions_2 = builder.equal(root.get(DELETED), false);
    
    query.select(root).where(builder.or(restrictions_1,restrictions_2));
    
    
    final var result = session.createQuery(query).getResultList();
    return new PageImpl<>(result, pageable, result.size());
}

The flow does not seem to reach after root.join.

EDIT-2

The relations are as follows:

String PERSON_RELATIONSHIP = "person.address"

String DEPARTMENT_RELATION = "person.department"

and both person, address, department themselves are classes which extend Entity

1 Answers

I guess the associations you try to fetch i.e. PERSON_RELATION or DEPARTMENT_RELATION are collections? In such a case, it is not possible to directly do pagination on the entity level with Hibernate. You would have to fetch the ids first and then do a second query to fetch just the entities with the matching ids.

You could use Blaze-Persistence on top of Hibernate though which has a special pagination API that does these tricks for you behind the scenes. Here is the documentation about the pagination: https://persistence.blazebit.com/documentation/core/manual/en_US/index.html#pagination

There is also a Spring Data integration, so you could also use the Spring Data pagination convention along with Blaze-Persistence Entity-Views which are like Spring Data Projections on steroids. You'd use Page<DriverView> findByDeletedFalseOrDeletedNull(Pageable p) with

@EntityView(Driver.class)
interface DriverView {
  Long getId();
  String getName();
  PersonView getPersonRelation();
  DepartmentView getDepartmentRelation();
}
@EntityView(Person.class)
interface PersonView {
  Long getId();
  String getName();
}
@EntityView(Department.class)
interface DepartmentView {
  Long getId();
  String getName();
}

Using entity views will only fetch what you declare, nothing else. You could also use entity graphs though:

@EntityGraph(attributePaths = {"personRelation", "departmentRelation"})
Page<Driver> findByDeletedFalseOrDeletedNull(Pageable p);
Related