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

2022-08-31 20:47:40

我正在使用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)

但是,以下查询有效:

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);

(但它是SQL注入倾向...)

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


答案 1

未为本机查询定义命名参数的使用。来自 JPA 规范(第 3.6.3 节命名参数):

命名参数遵循第 4.4.1 节中定义的标识符规则。命名参数的使用适用于 Java 持久性查询语言,而不是为本机查询定义的。只有位置参数绑定可以移植地用于本机查询

因此,请尝试以下操作:

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);

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


答案 2

也许你可以替换

'POINT(:lon :lat)'

'POINT(' || :lon || ' ' || :lat || ')'

这样,参数位于常量字符串之外,应由查询分析器识别。


推荐