簡體   English   中英

JPA/Hibernate 本機查詢無法識別參數

[英]JPA/Hibernate Native Queries do not recognize Parameters

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

本機查詢未定義命名參數的使用。 來自 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);

請注意,在 JPA >= 2.0 中,您可以在本機查詢中使用命名參數。

也許你可以更換

'POINT(:lon :lat)'

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

這樣參數就在常量字符串之外,應該被查詢解析​​器識別。

我有一個類似的問題,發現在本機查詢中可以用問號設置參數。 嘗試這個:

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

你也可以擺脫整個

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

調用並將其替換為

ST_Point(:lon,:lat)

那么你不必擔心報價。

Pascal 的回答是正確的,但是……您的解決方案如何容易發生 SQL 注入? 如果您在示例中使用String.format和參數類型%f ,那么除數字之外的任何其他內容都會引發 java.util.IllegalFormatConversionException。 沒有像“xxx' OR 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

所以,這個想法是使用 Jörn Horstmann 建議的連接技巧來強制 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);

非常感謝你的回答 !

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM