使用Postgres LTREE时如何将参数传递给JPA?

时间:2019-01-04 16:43:26

标签: postgresql hibernate spring-boot jpa spring-data-jpa

我有一个使用JPA的Spring Boot应用程序和一个具有ltree数据结构的Postgres表。

当我使用sql语句查询时有效,但当我传递参数时无效。

控制器

@GetMapping("/path")
ResponseEntity<?> findAllByPath() {

    List<Tree> allByPath = treeRepository.findAllByPath("A");

    return ResponseEntity.ok().body(allByPath);
}

存储库中的工作代码

@Query(value = "SELECT * FROM Tree WHERE path <@ 'A'", nativeQuery = true)
List<Tree> findAllByPath(@Param("pathToSearch") String pathToSearch);

*不是存储库中的工作代码

@Query(value = "SELECT * FROM Tree WHERE path <@ '" + ":pathToSearch" +"'", nativeQuery = true)
List<Tree> findAllByPath(@Param("pathToSearch") String pathToSearch);

错误

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Fri Jan 04 17:41:43 CET 2019
There was an unexpected error (type=Internal Server Error, status=500). could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet

Stacktrace

2019-01-04 17:41:43.357 DEBUG 33826 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    SELECT
        * 
    FROM
        Tree 
    WHERE
        path <@ ':pathToSearch'
Hibernate: 
    SELECT
        * 
    FROM
        Tree 
    WHERE
        path <@ ':pathToSearch'
2019-01-04 17:41:43.362  WARN 33826 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 42601
2019-01-04 17:41:43.363 ERROR 33826 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: syntax error at position 0
  Position: 34
2019-01-04 17:41:43.381 ERROR 33826 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause

org.postgresql.util.PSQLException: ERROR: syntax error at position 0
  Position: 34
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440) ~[postgresql-42.2.5.jar:42.2.5]

编辑: 当我尝试删除查询中的引号时,它失败并出现另一个错误。

@Query(value = "SELECT * FROM Tree WHERE path <@ :pathToSearch", nativeQuery = true)
List<Tree> findAllByPath(@Param("pathToSearch") String pathToSearch);

2019-01-08 12:52:25.213 DEBUG 18840 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
SELECT
    * 
FROM
    Tree 
WHERE
    path <@ ?
Hibernate: 
    SELECT
        * 
    FROM
        Tree 
    WHERE
        path <@ ?
2019-01-08 12:52:25.222 TRACE 18840 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [A]
2019-01-08 12:52:25.240  WARN 18840 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 42883
2019-01-08 12:52:25.240 ERROR 18840 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: operator does not exist: ltree <@ character varying
  Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
  Position: 31
2019-01-08 12:52:25.266 ERROR 18840 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause

org.postgresql.util.PSQLException: ERROR: operator does not exist: ltree <@ character varying
  Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
  Position: 31

1 个答案:

答案 0 :(得分:1)

我通过将参数强制转换为ltree来修复了它。 Repository中修改后的方法和查询为:

@Query(value = "SELECT * FROM Tree WHERE path <@ CAST(:pathToSearch AS ltree)", nativeQuery = true)
List<Tree> findAllByPath(@Param("pathToSearch") String pathToSearch);