В основном я пытаюсь выбрать поле, в котором я рассчитываю, используя запрос 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.
Отредактировано в соответствии с комментариями @BillyFrost
правильно, а где звонок CriteriaQuery.select или CriteriaQuery.multiselect?
@BillyFrost в данный момент отсутствует в коде, поскольку entityManager.createQuery(criteriaQuery) .setMaxResults(restaurantSearch.getSize()) .setFirstResult((restaurantSearch.getPage()) * restaurantSearch.getSize()) .getResultList(); возвращает список объектов. Которая не содержит рассчитанного поля расстояния. Что является частью моего вопроса :)
поэтому вызовите criteriaQuery.multiselect с идентификатором и рассчитанным предикатом, затем




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