Я использую Hibernate/JPA для выполнения собственных запросов PostGIS. Проблема с этими запросами состоит в том, что им нужны параметры, которые не имеют классического X = форма 'значения'.
Например, следующий катастрофический отказ строк
String queryString = "select * from Cell c where ST_DWithin(c.shape, SetSRID(ST_GeomFromEWKT('POINT(:lon :lat)'),4326), 0.1)";
Query query = Cell.em().createNativeQuery(queryString, Cell.class);
query.setParameter("lon", longitude);
query.setParameter("lat", latitude);
play.exceptions.JavaExecutionException: org.hibernate.QueryParameterException: could not locate named parameter [lon]
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:259)
at Invocation.HTTP Request(Play!)
Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryParameterException: could not locate named parameter [lon]
at org.hibernate.ejb.QueryImpl.setParameter(QueryImpl.java:358)
Следующий запрос работает однако:
String queryString = String.format("select * from Cell c where ST_DWithin(c.shape, SetSRID(ST_GeomFromEWKT('POINT(%f %f)'),4326), 0.1)", longitude, latitude);
Query query = Cell.em().createNativeQuery(queryString, Cell.class);
(но это является СКЛОННЫМ К ВНЕДРЕНИЮ SQL...),
Делает любой знает, как использовать setParameter()
в этом случае?
Возможно, вы можете заменить
'POINT(:lon :lat)'
на
'POINT(' || :lon || ' ' || :lat || ')'
Таким образом параметры находятся за пределами постоянных строк и должны распознаваться синтаксическим анализатором запросов.
Использование именованных параметров не определено для собственных запросов. Из спецификации JPA (раздел 3.6.3 Именованные параметры ):
Именованные параметры соответствуют правилам для идентификаторы, определенные в разделе 4.4.1. Использование именованных параметров применяется к язык запросов Java Persistence, и не определен для собственных запросов. Только привязка позиционного параметра может быть переносимым для собственных запросов .
Поэтому попробуйте вместо этого следующее:
String queryString = "select * from Cell c where ST_DWithin(c.shape, SetSRID(ST_GeomFromEWKT('POINT(?1 ?2)'),4326), 0.1)";
Query query = Cell.em().createNativeQuery(queryString, Cell.class);
query.setParameter(1, longitude);
query.setParameter(2, latitude);
Обратите внимание, что в JPA> = 2.0 вы можете использовать именованных параметров в собственных запросах.
Итак, идея заключалась в том, чтобы использовать трюк с конкатенацией, предложенный Йорном Хорстманном, чтобы заставить postgres распознать параметры. Следующий код работает :
String queryString = "select * from Cell c where ST_DWithin(c.shape, SetSRID(ST_GeomFromEWKT('POINT(' || :lon || ' ' || :lat || ')'),4326), 0.2)";
Query query = Cell.em().createNativeQuery(queryString, Cell.class);
query.setParameter("lon", longitude);
query.setParameter("lat", latitude);
Большое спасибо за ваши ответы!