JPA/Hibernate本机查询无法识别参数

use*_*054 46 java orm hibernate jpa postgis

我正在使用Hibernate/JPA来执行本机PostGIS查询.这些查询的问题是它们需要的参数不是经典的X ='value'形式.

例如,以下行崩溃

 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)
Run Code Online (Sandbox Code Playgroud)

但是,以下查询有效:

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);
Run Code Online (Sandbox Code Playgroud)

(但它易于SQL注入......)

有谁知道setParameter()在这种情况下如何使用?

Pas*_*ent 81

未为本机查询定义命名参数的使用.从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);
Run Code Online (Sandbox Code Playgroud)

请注意,在JPA> = 2.0中,您可以在本机查询中使用命名参数.

  • +1引用规范并提醒我这不便携.我实际上在hibernate项目中的本机查询中使用了命名参数,它工作正常.在另一个较旧的项目中,基于toplink essentials,所有本机查询都使用位置参数,所以我必须先知道这个并忘记:) (4认同)
  • 对于JPA位置参数,如"?1",你必须调用query.setParameter("1",经度); 等等/ (2认同)

Jör*_*ann 18

也许你可以替换

'POINT(:lon :lat)'
Run Code Online (Sandbox Code Playgroud)

'POINT(' || :lon || ' ' || :lat || ')'
Run Code Online (Sandbox Code Playgroud)

这样,参数不在常量字符串中,应该由查询解析器识别.

  • +1实际上确认问题的有趣技巧来自引号,而不是来自命名参数(尽管应该避免使用JPA). (3认同)