使用 ltree 本机命名查询休眠
hibernate with ltree native named query
我正在尝试 运行 包含 ltree
函数和运算符的 PostgreSQL 本机查询。
定义如下:
@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(?) 不喜欢 ~
运算符右侧的类型,但如您所见,我在后面的查询中使用了该字符串并且工作正常。
那么hibernate查询需要做什么才能运行查询成功?
编辑:
当我将 okm_path ~ :pathLike
替换为 "where okm_path ~ '*._root_.*' "
时,我将得到:
org.postgresql.util.PSQLException: ERROR: syntax error at position 0
错误
休眠:5.2.9.Final
postgresql: 9.2.23
错误
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
.
此处的问题是当您设置右侧的值时,
query.setParameter("pathLike", pathLike)
pathLike
是一个字符串。所以 Postgres 将此视为将 ltree 与字符串进行比较。当您直接执行 SQL 时,右侧被视为 ltree 表达式而不是字符串。
我不确定这是否可行,但您可以尝试将 ltree 直接转换为 varchar,但您可以试试这个吗?:
query.setParameter("pathLike", pathLike, Hibernate.OBJECT)
另见 Java type in JDBC to Postgres ltree
原来有lquery()
函数需要在lquery操作时调用
所以我的查询转换为
...
where okm_path ~ lquery(:pathLike)
...
这解决了问题
我正在尝试 运行 包含 ltree
函数和运算符的 PostgreSQL 本机查询。
定义如下:
@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(?) 不喜欢 ~
运算符右侧的类型,但如您所见,我在后面的查询中使用了该字符串并且工作正常。
那么hibernate查询需要做什么才能运行查询成功?
编辑:
当我将 okm_path ~ :pathLike
替换为 "where okm_path ~ '*._root_.*' "
时,我将得到:
org.postgresql.util.PSQLException: ERROR: syntax error at position 0
错误
休眠:5.2.9.Final
postgresql: 9.2.23
错误
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
.
此处的问题是当您设置右侧的值时,
query.setParameter("pathLike", pathLike)
pathLike
是一个字符串。所以 Postgres 将此视为将 ltree 与字符串进行比较。当您直接执行 SQL 时,右侧被视为 ltree 表达式而不是字符串。
我不确定这是否可行,但您可以尝试将 ltree 直接转换为 varchar,但您可以试试这个吗?:
query.setParameter("pathLike", pathLike, Hibernate.OBJECT)
另见 Java type in JDBC to Postgres ltree
原来有lquery()
函数需要在lquery操作时调用
所以我的查询转换为
...
where okm_path ~ lquery(:pathLike)
...
这解决了问题