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
- Spring Boot + JPA:忽略列名称注释
- 如何避免使用Hibernate HQL结果的types安全警告?
- hibernate错误:org.hibernate.NonUniqueObjectException:具有相同标识符值的不同对象已经与会话关联
- hibernate5: – org.hibernate.MappingException:未知的实体
- 使用Hibernate注释的文本字段
- hibernateexception:org.hibernate.AnnotationException:没有为实体指定标识符:com..domain.idea.MAE_MFEView
- MySQL抛出错误的string值错误
- 如何通过在Hibernate中使用限制和标准来实现“不在”?
- Spring事务和hibernate.current_session_context_class