спящий с ltree нативным запросом - PullRequest
0 голосов
/ 26 декабря 2018

Я пытаюсь запустить собственный запрос PostgreSQL, который содержит ltree функции и операторы.

Вот определение:

@NamedNativeQuery(
            name = "pathSegmentQuery",
            query = "select ltree2text(okm_path) as okm_path, " +
                    "       index(okm_path, text2ltree(:lastSegment)) + 2 <> nlevel(okm_path) as haschild, " +
                    "       case " +
                    "         when index(okm_path, text2ltree(:lastSegment)) + 1 <> nlevel(okm_path) " +
                    "                 then ltree2text(subpath(okm_path, index(okm_path, text2ltree(:lastSegment)) + 1, 1)) " +
                    "           end as child " +
                    "from document " +
                    "where okm_path ~ :pathLike " +
                    "and " +
                    "index(okm_path, text2ltree(:path)) + 1 <> nlevel(okm_path) ",
            resultSetMapping = "pathSegmentQueryRSMapping")

вызвано как:

public List<PathSegment> getPathChildren(String path, String lastSegment) {
    Query query = entityManager.createNamedQuery("pathSegmentQuery");
    String pathLike = "'*." + path + ".*'";

    query.setParameter("path", path);
    query.setParameter("pathLike", pathLike);
    query.setParameter("lastSegment", lastSegment);

    return query.getResultList();
}

результат - ошибка ERROR: operator does not exist: ltree ~ character varying.

, когда я пытаюсь выполнить запрос непосредственно к базе данных, он работает нормально:

select ltree2text(okm_path) as okm_path,
   index(okm_path, text2ltree('_root_')) + 2 <> nlevel(okm_path) as haschild,
   case
     when index(okm_path, text2ltree('_root_')) + 1 <> nlevel(okm_path)
             then ltree2text(subpath(okm_path, index(okm_path, text2ltree('_root_')) + 1, 1))
       end as child
from document
where
    okm_path ~ '*._root_.*'
and
    index(okm_path, text2ltree('_root_')) + 1 <> nlevel(okm_path)

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

Так что мне нужно сделать с запросом гибернации, чтобы выполнить запросуспешно?

РЕДАКТИРОВАТЬ: когда я заменяю okm_path ~ :pathLike на "where okm_path ~ '*._root_.*' " Мне будет выдано:

org.postgresql.util.PSQLException: ERROR: syntax error at position 0 Ошибка

Спящий режим: 5.2.9. Окончательный

postgresql: 9.2.23

Ответы [ 2 ]

0 голосов
/ 28 декабря 2018

оказалось, что есть функция lquery(), которую нужно вызывать, когда вы выполняете операции с lquery.

, поэтому мой запрос преобразуется в

...
where okm_path ~ lquery(:pathLike)
...

, и это решает проблему

0 голосов
/ 26 декабря 2018

Ошибка

operator does not exist: ltree ~ character varying

должна читаться как

operator does not exist: <left_data_type> <operator> <right_data_type> varying

Это означает, что оператор не определен для этих типов данных.Это происходит, когда, например, левая часть оператора представляет собой целое число, а правая часть представляет собой varchar, ошибка в котором будет равна ERROR: operator does not exist: integer = character varying.

Проблема здесь в том, что вы устанавливаете значение для rightсторона,

query.setParameter("pathLike", pathLike) 

pathLike является строкой.Таким образом, Postgres видит в этом сравнение дерева со строкой.Когда вы выполняете SQL напрямую, правая часть воспринимается как выражение ltree, а не как строка.

Я не уверен, что это сработает, но вы можете попробовать, что ltree можно напрямую привести к varchar, но можете ли выпопробуйте это:

query.setParameter("pathLike", pathLike, Hibernate.OBJECT)

См. также Тип Java в JDBC для Postgres ltree

...