JPA / Hibernate原生查询不识别参数

我正在使用Hibernate / JPA来执行原生的PostGIS查询。 这些查询的问题是他们需要的参数不是经典的X ='value'forms。

例如,以下行会崩溃

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

没有为本地查询定义使用命名参数。 从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中,您可以在本机查询中使用命名参数。

也许你可以replace

 'POINT(:lon :lat)' 

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

这样,参数在常量string之外,应该被查询parsing​​器识别。

我有一个类似的问题,并发现参数可以在本机查询中设置问号。 尝试这个:

 String queryString = "select * from Cell c where ST_DWithin(c.shape, SetSRID(ST_GeomFromEWKT('POINT(? ?)'),4326), 0.1)"; Query query = Cell.em().createNativeQuery(queryString, Cell.class); query.setParameter(1, longitude); query.setParameter(2, latitude); 

所以,这个想法是使用JörnHorstmann提出的拼接技巧来强制postgres识别参数。 以下代码工作:

 String queryString = "select * from Cell c where ST_DWithin(c.shape, SetSRID(ST_GeomFromEWKT('POINT(' || :lon || ' ' || :lat || ')'),4326), 0.2)"; Query query = Cell.em().createNativeQuery(queryString, Cell.class); query.setParameter("lon", longitude); query.setParameter("lat", latitude); 

非常感谢您的回答!

你也可以摆脱整个

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

打电话并更换

 ST_Point(:lon,:lat) 

那么你不必担心报价。

Pascal的答案是正确的,但是…你的解决schemeSQL注入容易吗? 如果你在你的例子中使用了String.format和parmatertypes%f ,那么除了数字之外的任何东西都会抛出java.util.IllegalFormatConversionExceptionexception。 没有像“xxx”或“1 = 1 – ”那样的可能性。

要小心,在String.format使用%s是SQL注入就绪。

我面临类似的问题。 我在存储库中使用本地查询?1。 它通过围绕括号括起来的参数来解决它,如下所示。

 SELECT * FROM XYZ WHERE ABC = (?1) 

http://javageneralist.blogspot.com/2011/06/jpa-style-positional-param-was-not.html