Исключение пространственного запроса Hibernate, но в консоли postgres работает

Я пытаюсь выполнить этот запрос в своем Java-коде, используя Hibernate и Hibernate Spatial:

Query q = s.createQuery("SELECT c FROM crimes c WHERE ST_DWITHIN(ST_MakeLine(ARRAY['SRID=4326;POINT(-49.30621000000001 -25.515020000000003)','SRID=4326;POINT(-49.30619 -25.515770000000003)','SRID=4326;POINT(-49.306180000000005 -25.5162)','SRID=4326;POINT(-49.305780000000006 -25.5162)']), c.location, 0.0001) = true;");

Но этот запрос вызывает исключение:

e = (org.hibernate.hql.internal.ast.QuerySyntaxException) org.hibernate.hql.internal.ast.QuerySyntaxException: expecting CLOSE_BRACKET, found ',' near line 1, column 151 [SELECT c FROM com.safecity.server.db.model.EntityCrime c WHERE ST_DWITHIN(ST_MakeLine(ARRAY['SRID=4326;POINT(-49.305820000000004 -25.515330000000002)','SRID=4326;POINT(-49.306200000000004 -25.515340000000002)','SRID=4326;POINT(-49.30619 -25.515770000000003)','SRID=4326;POINT(-49.306180000000005 -25.5162)','SRID=4326;POINT(-49.305780000000006 -25.5162)']), c.location, 0.0001) = true]

Я проверил запрос, и я не могу найти ошибку. Но если я получу тот же запрос и выполню его на консоли postgres, запрос будет выполнен без ошибок и вернет правильное значение.

Пожалуйста, кто-нибудь может мне помочь? Спасибо.


person brunoroberto    schedule 02.10.2016    source источник
comment
При этом упростите свой запрос. ST_DWITHIN() уже возвращает boolean. Не нужно добавлять = true, это просто шум: SELECT c FROM crimes c WHERE ST_DWITHIN(ST_MakeLine(ARRAY[ ... ]), c.location, 0.0001)   -  person Erwin Brandstetter    schedule 02.10.2016
comment
Спасибо, я изменю это   -  person brunoroberto    schedule 02.10.2016


Ответы (3)


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

Query q = s.createSQLQuery("SELECT c FROM crimes c WHERE ST_DWITHIN(ST_MakeLine(ARRAY['SRID=4326;POINT(-49.30621000000001 -25.515020000000003)','SRID=4326;POINT(-49.30619 -25.515770000000003)','SRID=4326;POINT(-49.306180000000005 -25.5162)','SRID=4326;POINT(-49.305780000000006 -25.5162)']), c.location, 0.0001) = true;");

Используйте createSQLQuery() вместо createQuery(), если вы хотите создать собственный запрос базы данных вместо HQL.

person Rohit Gaikwad    schedule 02.10.2016
comment
Я попробовал ваше предложение, но теперь происходит другое исключение: e = (org.hibernate.MappingException) org.hibernate.MappingException: нет сопоставления диалектов для типа JDBC: 1111. Знаете почему? - person brunoroberto; 02.10.2016
comment
Это исключение сопоставления типов, в котором говорится, что тип столбца не может быть сопоставлен с типом базы данных с помощью спящего режима. Если вы не можете правильно отобразить вещи, добавьте весь код (класс pojo, структуру таблицы и основной класс, в котором вы запускаете свой запрос). - person Rohit Gaikwad; 02.10.2016
comment
Это странно, потому что я использую другой запрос с той же таблицей и объектом, и он не выдает никаких исключений. Но я использовал в этом другом запросе только createQuery вместо createSQLQuery. - person brunoroberto; 02.10.2016
comment
помните, используя собственные запросы, вы не получите объект. вместо этого вы получите значения столбца напрямую (так же, как с простым оператором jdbc), а не объект. Используя createSQLQuery, он возвращает объект, его запрос HQL. Если вы хотите использовать HQL, вам нужно изменить свой запрос в формате HQL и использовать оператор createQuery. - person Rohit Gaikwad; 02.10.2016
comment
небольшая опечатка в комментарии выше; createQuery возвращает объект - person Rohit Gaikwad; 03.10.2016

Я решил эту проблему, изменив запрос для этого:

Query q = s.createQuery("SELECT c FROM crimes c WHERE ST_DWITHIN(ST_GeomFromText('LINESTRING(-49.305820000000004 -25.515330000000002,-49.306200000000004 -25.515340000000002,-49.30619 -25.515770000000003,-49.306180000000005 -25.5162,-49.305780000000006 -25.5162)', 4326), c.location, 0.0001) = true");

Не знаю почему, но это работает.

Спасибо за помощь.

person brunoroberto    schedule 02.10.2016

Я встречал подобные проблемы с конструкторами ARRAY. в спящем режиме раньше.

Замените литералом массива (и, возможно, приведением типа), чтобы он работал. Простой строковый литерал позволит избежать различных осложнений в общении.

Вы используете функцию PostGis ST_MakeLine(), принимающую массив geometry в качестве входного параметра.

геометрия ST_MakeLine(geometry[] geoms_array)

So:

Query q = s.createQuery(
  "SELECT c FROM crimes c
   WHERE  ST_DWITHIN(ST_MakeLine('{SRID=4326;POINT(-49.30621000000001 -25.515020000000003)
                                  ,SRID=4326;POINT(-49.30619 -25.515770000000003)
                                  ,SRID=4326;POINT(-49.306180000000005 -25.5162)
                                  ,SRID=4326;POINT(-49.305780000000006 -25.5162)}'::geometry[]), c.location, 0.0001)");

Это также объясняет, почему ваш альтернативный ответ, предоставляющий строку (как строковый литерал!) также работает.

Также упрощено логическое выражение в предложении WHERE мне понравилось. Добавление = true — это просто шум.

person Erwin Brandstetter    schedule 02.10.2016