Критерии JPA — псевдонимы, которые не работают при выборе агрегации

В проекте, использующем Hibernate 6.4, я использую Criteria API, предоставляемый через API персистентности Jakarta (зависимость от Hibernate). Однако я столкнулся с ошибкой при использовании псевдонимов в функциях агрегирования при выборе.

Предположим, у нас есть сущность MyEntity со следующими атрибутами:

  • id типа Integer (для этой задачи он нам не нужен)
  • attr1 типа String
  • attr2 типа Целое число

Будем считать, что аннотированный класс правильно написан согласно этому описанию и правильно импортирован во время выполнения приложения.

Здесь я хочу выбрать значения attr1 и сумму значений attr2 из таблицы, связанной с этой сущностью, и упорядочить результат по сумме значений attr2.

Вот код, соответствующий тому, что я написал в своем проекте (точный код дать не могу, поэтому проиллюстрирую то, что я сделал, на этом примере):

public class MyClass {
    public List<Object[]> myMethod(Session session, String orderAttribute) {
        CriteriaBuilder cb = session.getCriteriaBuilder();
        CriteriaQuery<?> cq = cb.createQuery(Object[].class);
        Root<MyEntity> root = cq.from(MyEntity.class);

        List<Selection<?>> selections = new ArrayList<>();

        selections.add(root.get("attr1"));

        Selection<Number> sumAttr2 = cb.sum(root.get("attr2")).alias("sumAttr2");
        selections.add(sumAttr2);

        cq.multiselect(selections);
        cq.orderBy(cb.asc(root.get(orderAttribute)));

        Query<Object[]> query = session.createQuery(cq);
        List<Object[]> result = query.getResultList();

        return result;
    }
}

Когда я выполняю это с помощью orderAttribute = "attr1", все работает как положено. Но когда я выполняю запрос с помощью orderAttribute = "sumAttr2", он терпит неудачу и выдает следующую ошибку:

org.hibernate.query.sqm.PathElementException: Could not resolve attribute 'sumAttr2' of 'com.example.MyClass'

У меня нет SQL-запроса, сгенерированного во время ошибки, потому что, похоже, он дает сбой при создании запроса, а не во время его выполнения. Однако у меня есть запрос случая orderAttribute = "attr1", который соответствует этому:

select me1_0.attr1,sum(me1_0.attr2) from my_entity me1_0 order by 1

Я предполагаю, что проблема связана с псевдонимом, потому что он не отображается в запросе (у меня нет sum(me1_0.attr2) as sumAttr2), и когда я пытаюсь упорядочить результат по этому отсутствующему псевдониму, у меня возникает ошибка, потому что API " думаю», это должно быть атрибутом сущности.

Я пробовал несколько способов написать псевдоним, но ни один из них не сработал.

Selection<Number> sumAttr2 = cb.sum(root.get("attr2")).alias("sumAttr2");
selections.add(sumAttr2);

Expression<Number> sumAttr2 = criteriaBuilder.sum(root.get("attr2"));
Selection<Number> sumAttr2Selection = sumAttr2.alias("sumAttr2");
selections.add(sumAttr2Selection);

Expression<Number> sumAttr2 = criteriaBuilder.sum(root.get("attr2"));
sumAttr2.alias("sumAttr2");
selections.add(sumAttr2)

Вы можете помочь мне ? Я хочу получить что-то эквивалентное следующему запросу, используя Criteria API:

select me1_0.attr1,sum(me1_0.attr2) as sumAttr2 from my_entity me1_0 order by sumAttr2
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
110
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Хорошо, я нашел решение: нам нужно использовать объект Expression, возвращаемый методом CriteriaBuilder.sum().

Вот моя реализация:

public class MyClass {
    public List<Object[]> myMethod(Session session, String orderAttribute) {
        CriteriaBuilder cb = session.getCriteriaBuilder();
        CriteriaQuery<?> cq = cb.createQuery(Object[].class);
        Root<MyEntity> root = cq.from(MyEntity.class);

        // Selections
        List<Selection<?>> selections = new ArrayList<>();

        selections.add(root.get("attr1"));

        Expression<Number> sumAttr2 = criteriaBuilder.sum(root.get("attr2"));
        Selection<Number> sumAttr2Selection = sumAttr2.alias("sumAttr2");
        selections.add(sumAttr2Selection);

        cq.multiselect(selections);
        // End of selections

        // Order
        Expression<?> sortIndex;
        switch (criteres.getColonneTri()) {
            case "sumAttr2":
                sortIndex = somme;
                break;
            // Here, other alias cases if any.
            default:
                sortIndex = root.get(orderAttribute);
                break;
        }
        cq.orderBy(cb.asc(sortIndex));
        // End of order

        Query<Object[]> query = session.createQuery(cq);
        List<Object[]> result = query.getResultList();

        return result;
    }
}

И соответствующий SQL-запрос, сгенерированный Hibernate/JPA:

select me1_0.attr1,sum(me1_0.attr2) from my_entity me1_0 order by 2

Здесь следует отметить две вещи:

  • SQL-запрос использует индекс столбца, а не его имя, для выполнения порядка по операции.
  • метод alias(), согласно документу со спецификациями Jakarta Persistence (версия 3.1), применит заданный псевдоним к результату запроса при выполнении. Он не применяет псевдоним непосредственно к SQL-запросу.

Другие вопросы по теме