JPA - выберите поле с расчетом

В основном я пытаюсь выбрать поле, в котором я рассчитываю, используя запрос Postgres postgis ST_distance_sphere.

Приведенный ниже код позволяет мне отфильтровывать результаты в зависимости от расстояния. Если расстояние больше заданного значения, запись фильтруется. Я создал следующий запрос с помощью указанного ниже построителя предикатов. Однако я также хочу выбрать значение расстояния, возвращаемое функцией ST_distance_sphere, как «расстояние»

Вот как я использую JPQL:

    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<RestaurantEntity> criteriaQuery = criteriaBuilder.createQuery(RestaurantEntity.class).distinct(true);

    Root<RestaurantEntity> restaurantEntityRoot = criteriaQuery.from(RestaurantEntity.class);
    Predicate[] searchPredicates = createPredicates(criteriaBuilder, restaurantEntityRoot, restaurantSearch);
    List<Order> orders = getSortingOrders(restaurantSearch, criteriaBuilder, restaurantEntityRoot);

    criteriaQuery.where(searchPredicates).orderBy(orders);

    List<RestaurantEntity> searchResults = entityManager.createQuery(criteriaQuery)
            .setMaxResults(restaurantSearch.getSize())
            .setFirstResult((restaurantSearch.getPage()) * restaurantSearch.getSize())
            .getResultList();

Вот функция searchByDistance и класс JpaRestaurantPredicateBuilder, который я использую.

class JpaRestaurantPredicateBuilder {
        private CriteriaBuilder criteriaBuilder;
        private Root<RestaurantEntity> restaurantEntityRoot;
        private List<Predicate> predicateList;
        JpaRestaurantPredicateBuilder(CriteriaBuilder criteriaBuilder, Root<RestaurantEntity> restaurantEntityRoot) {
            this.criteriaBuilder = criteriaBuilder;
            this.restaurantEntityRoot = restaurantEntityRoot;
            this.predicateList = new ArrayList<>();
        }

        JpaRestaurantPredicateBuilder searchByDistance(Float lon, Float lat, Long maxDistance) {
            Point userLocation = new GeometryFactory().createPoint(new Coordinate(lon, lat));
            Join address = this.restaurantEntityRoot.join("addressEntity", JoinType.INNER);
            predicateList.add(new WithinDistancePredicate((CriteriaBuilderImpl) criteriaBuilder, address.get("location"), userLocation,  maxDistance));
            return this;
        }

        Predicate[] buildArray() {
            return predicateList.toArray(new Predicate[0]);
        }
    }

Вот createPredicates:

    private Predicate[] createPredicates(CriteriaBuilder criteriaBuilder, Root<RestaurantEntity> restaurantEntityRoot, RestaurantSearch restaurantSearch) {
            return new JpaRestaurantPredicateBuilder(criteriaBuilder, restaurantEntityRoot)
                    .chainId(restaurantSearch.getChainId())
                    .searchTerm(retrieveRestaurantIdsForSearchTerm(restaurantSearch.getSearchTerm()))
                    .cityIdAndDistrictId(restaurantSearch.getCityId(), restaurantSearch.getDistrictId())
                    .status(restaurantSearch.getStatus())
                    .searchByDistance(restaurantSearch.getLon(), restaurantSearch.getLat(), restaurantSearch.getMaxDistance())
                    .buildArray();
        }

А вот сгенерированный sql:

    select distinct restaurant0_.id
    from restaurant restaurant0_
       inner join address addressent1_ on restaurant0_.address_id = addressent1_.id
    where st_distance_sphere(addressent1_.location, ?) < 1000
    order by restaurant0_.id desc
    limit ?

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

    select distinct restaurant0_.id,
    st_distance_sphere(addressent1_.location, ?) as distance
    from restaurant restaurant0_
       inner join address addressent1_ on restaurant0_.address_id = addressent1_.id
    where st_distance_sphere(addressent1_.location, ?) < 1000
    order by restaurant0_.id desc
    limit ?

Других ответов на этот вопрос найти не удалось. Как я могу выполнить этот запрос с помощью JPA? Я безуспешно пытался использовать метод select CriteriaQuery.

Поскольку вы не публикуете информацию об использовании JPQL или критериев, то чего вы ожидаете от людей. Все эти вызовы методов предположительно являются вашим кодом.

user3973283 27.11.2018 15:55

Отредактировано в соответствии с комментариями @BillyFrost

Berkay Dincer 27.11.2018 16:02

правильно, а где звонок CriteriaQuery.select или CriteriaQuery.multiselect?

user3973283 27.11.2018 16:27

@BillyFrost в данный момент отсутствует в коде, поскольку entityManager.createQuery(criteriaQuery) .setMaxResults(restaurantSearch.getSize()) .setFirstResult((restaurantSearch.getPage()) * restaurantSearch.getSize()) .getResultList(); возвращает список объектов. Которая не содержит рассчитанного поля расстояния. Что является частью моего вопроса :)

Berkay Dincer 27.11.2018 19:54

поэтому вызовите criteriaQuery.multiselect с идентификатором и рассчитанным предикатом, затем

user3973283 28.11.2018 09:34
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
520
0

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