Hibernate Criteria FetchMode.JOIN выполняет отложенную загрузку - PullRequest
3 голосов
/ 06 августа 2020

У меня есть конечная точка с разбивкой на страницы, которая внутренне использует критерии гибернации для получения определенных объектов и отношений. FetchMode установлен как FetchMode.JOIN. Когда я пытаюсь попасть в конечную точку, запрос, кажется, работает нормально для нескольких страниц, но затем возникает ошибка:

could not initialize proxy - no Session

Метод выглядит следующим образом:

@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();
}

Кроме того, вызов findAllNotDeleted осуществляется из метода, помеченного как @Transactional.

Не уверен, что происходит не так. Любая помощь будет принята с благодарностью.

EDIT Я читал, что FetchMode.Join не работает с Ограничениями. Поэтому я попытался реализовать его, используя CriteriaBuilder, но снова столкнулся с проблемой.

@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());
}

Кажется, что поток не достигает после root.join.

EDIT-2

Связи следующие:

Строка PERSON_RELATIONSHIP = "person.address"

Строка DEPARTMENT_RELATION = "person.department"

и обе person, address, department сами по себе являются классами, которые extend Entity

1 Ответ

0 голосов
/ 07 августа 2020

Думаю, ассоциации, которые вы пытаетесь получить, например, PERSON_RELATION или DEPARTMENT_RELATION, являются коллекциями? В таком случае невозможно напрямую выполнить разбиение на страницы на уровне сущности с помощью Hibernate. Вам нужно будет сначала получить идентификаторы, а затем выполнить второй запрос, чтобы получить только объекты с соответствующими идентификаторами.

Вы можете использовать Blaze-Persistence поверх Hibernate, хотя у которого есть специальный API пагинации, который делает эти трюки за вас за кулисами. Вот документация о разбиении на страницы: https://persistence.blazebit.com/documentation/core/manual/en_US/index.html#pagination

Существует также интеграция Spring Data, поэтому вы также можете использовать соглашение о разбивке на страницы Spring Data вместе с Blaze-Persistence Entity-Views, которые похожи на прогнозы Spring Data на стероидах. Вы должны использовать Page<DriverView> findByDeletedFalseOrDeletedNull(Pageable p) с

@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();
}

. Использование представлений сущностей будет извлекать только то, что вы объявляете, и ничего больше. Вы также можете использовать графы сущностей:

@EntityGraph(attributePaths = {"personRelation", "departmentRelation"})
Page<Driver> findByDeletedFalseOrDeletedNull(Pageable p);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...