PostgreSQL 9.4,在我的 JPA namedQuery 中使用 earth_distance
PostgreSQL 9.4, use earth_distance in my JPA namedQuery
我有一个 table 站点存储了我的站点信息以及纬度和经度。
ozssc=> \d site;
......
site_latitude | double precision |
site_longitude | double precision |
......
我添加到我的 PostgreSQL 服务器 9.4.3
CREATE EXTENSION cube;
CREATE EXTENSION earthdistance;
所有功能都已添加到我的数据库中,我将功能所有者更改为我的登录用户。
当我尝试将 PSQL 连接到我的服务器并执行时:
ozssc=> select * from site s where earth_box('-28.175613','153.52578399999993',100000) @> ll_to_earth(s.site_latitude,s.site_longitude);
ERROR: function earth_box(unknown, unknown, integer) does not exist
LINE 1: select * from site s where earth_box('-28.175613','153.52578...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
当我尝试将 earth_box 函数放入 JPA 的命名查询中时:
@NamedQuery(name = "SiteEntity.findByEarthDistance", query = "SELECT s FROM SiteEntity s WHERE earth_box((ll_to_earth( :positionLatitude, :positionLongitude), :range) @> ll_to_earth(s.siteLatitude,s.siteLongitude))"),
我的 intelliJ 抱怨没有函数匹配??
当我尝试将我的 JAVAEE 应用程序部署到我的 webLogic 12c 时,我发现错误如下:
Message icon - Error An error occurred during activation of changes, please see the log for details.
Message icon - Error Exception [EclipseLink-0] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.JPQLException Exception Description: Syntax error parsing [SELECT s FROM SiteEntity s WHERE earth_box((ll_to_earth( :positionLatitude, :positionLongitude), :range) > ll_to_earth(s.siteLatitude,s.siteLongitude))]. [33, 151] The expression is not a valid conditional expression.
Message icon - Error Substituted for missing class Exception [EclipseLink-0] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd) - org.eclipse.persistence.exceptions.JPQLException Exception Description: Syntax error parsing [SELECT s FROM SiteEntity s WHERE earth_box((ll_to_earth( :positionLatitude, :positionLongitude), :range) > ll_to_earth(s.siteLatitude,s.siteLongitude))]. [33, 151] The expression is not a valid conditional expression.
我迷路了,请问有没有人能帮帮我!!
再次编辑
我发现PostgreSQL 9.4的earth_box函数肯定有一些bug,它不能总是得到正确的结果集,我不得不把它改成earth_distance函数并使用多选投影为了使其运行良好,较新的 namedQuery 为:
@NamedQuery(name = "SiteEntity.findBySiteLNR", query = "SELECT s, FUNC('earth_distance', FUNC('ll_to_earth',:positionLatitude, :positionLongitude), FUNC('ll_to_earth',s.siteLatitude,s.siteLongitude)) AS dfcl " +
"FROM SiteEntity s WHERE dfcl < :range ORDER BY dfcl"),
我没有使用 hibernate,而是使用 EclipseLink 和 JPA 2.1,EJB 容器是 Weblogic 12C,EJB 规范 3.1。
我认为提示说明了一切:您需要添加显式类型转换。
您可以通过添加双分号和要将其转换为的类型来实现。即
'-28.175613'::text
或者函数期望的任何内容。
经过大约 4 个小时的努力,我找到了解决方案。主要是,因为它是来自 JPA 的函数调用,所以必须知道一些技巧。
PSQL 语句为:
select * from site s where earth_box(ll_to_earth(-28.175613,153.52578399999993),100000) @> ll_to_earth(s.site_latitude,s.site_longitude);
JPA namedQuery 为:
@NamedQuery(name = "SiteEntity.findByEarthDistance", query = "SELECT s FROM SiteEntity s WHERE FUNC('earth_box', FUNC('ll_to_earth',:positionLatitude, :positionLongitude), :range) > FUNC('ll_to_earth',s.siteLatitude,s.siteLongitude)"),
JPA 中的嵌套函数调用也可以,谢谢!
强烈建议使用 FUNCTION 而不是 FUNC(以前的实现:http://www.eclipse.org/eclipselink/documentation/2.6/jpa/extensions/jpql.htm#func)。 EclipseLink 支持按 FUNCTIONS 排序和分组,但它不适用于 FUNC。
@NamedQuery(name = "SiteEntity.findByEarthDistance", query = "SELECT s FROM SiteEntity s WHERE FUNCTION('earth_box', FUNCTION('ll_to_earth',:positionLatitude, :positionLongitude), :range) > FUNCTION('ll_to_earth',s.siteLatitude,s.siteLongitude)")
@Query(
"""
FROM Place pl
WHERE
FUNCTION('cube_contains',
FUNCTION('earth_box',
FUNCTION('ll_to_earth', :latitude, :longitude),
:radiusInMeters),
FUNCTION('ll_to_earth', pl.latitude, pl.longitude)
) = TRUE
""")
fun getPlacesNear(
pageable: Pageable,
@Param("latitude") latitude: Double,
@Param("longitude") longitude: Double,
@Param("radiusInMeters") radiusInMeters: Int
): Page<Place>
这对寻呼和远程支持非常有效
出于某种奇怪的原因
@Query(
"""
FROM Place pl
WHERE
FUNCTION('ll_to_earth', pl.latitude, pl.longitude)
< FUNCTION('earth_box', FUNCTION('ll_to_earth', :latitude, :longitude), :radiusInMeters)
""")
https://www.postgresql.org/docs/9.5/cube.html#CUBE-GIST-OPERATORS
由于某些奇怪的原因,“<”无法正常工作,因为“<”在 postgres 中没有被正确解释,并给出了错误的结果。
对于 postgres,您需要 spring JPA 无法解释的 '@<' 符号,所以我不得不切换到使用 cube_contains 函数
我本可以使用 native_query = true 但这不会给我分页支持,这就是我切换到 JPA 查询的原因。
所以如果你不需要分页,你可以使用下面的。
@Query(
"""SELECT *, earth_distance(ll_to_earth(:latitude, :longitude), ll_to_earth(latitude, longitude)) as distance
FROM place
WHERE (earth_box(ll_to_earth(:latitude, :longitude), :radiusInMeters) @> ll_to_earth(latitude, longitude))
ORDER BY distance ASC
""", nativeQuery = true)
fun getPlacesNear(
@Param("latitude") latitude: Double,
@Param("longitude") longitude: Double,
@Param("radiusInMeters") radiusInMeters: Int
): List<Place>?
我有一个 table 站点存储了我的站点信息以及纬度和经度。
ozssc=> \d site;
......
site_latitude | double precision |
site_longitude | double precision |
......
我添加到我的 PostgreSQL 服务器 9.4.3
CREATE EXTENSION cube;
CREATE EXTENSION earthdistance;
所有功能都已添加到我的数据库中,我将功能所有者更改为我的登录用户。
当我尝试将 PSQL 连接到我的服务器并执行时:
ozssc=> select * from site s where earth_box('-28.175613','153.52578399999993',100000) @> ll_to_earth(s.site_latitude,s.site_longitude);
ERROR: function earth_box(unknown, unknown, integer) does not exist
LINE 1: select * from site s where earth_box('-28.175613','153.52578...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
当我尝试将 earth_box 函数放入 JPA 的命名查询中时:
@NamedQuery(name = "SiteEntity.findByEarthDistance", query = "SELECT s FROM SiteEntity s WHERE earth_box((ll_to_earth( :positionLatitude, :positionLongitude), :range) @> ll_to_earth(s.siteLatitude,s.siteLongitude))"),
我的 intelliJ 抱怨没有函数匹配??
当我尝试将我的 JAVAEE 应用程序部署到我的 webLogic 12c 时,我发现错误如下:
Message icon - Error An error occurred during activation of changes, please see the log for details.
Message icon - Error Exception [EclipseLink-0] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.JPQLException Exception Description: Syntax error parsing [SELECT s FROM SiteEntity s WHERE earth_box((ll_to_earth( :positionLatitude, :positionLongitude), :range) > ll_to_earth(s.siteLatitude,s.siteLongitude))]. [33, 151] The expression is not a valid conditional expression.
Message icon - Error Substituted for missing class Exception [EclipseLink-0] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd) - org.eclipse.persistence.exceptions.JPQLException Exception Description: Syntax error parsing [SELECT s FROM SiteEntity s WHERE earth_box((ll_to_earth( :positionLatitude, :positionLongitude), :range) > ll_to_earth(s.siteLatitude,s.siteLongitude))]. [33, 151] The expression is not a valid conditional expression.
我迷路了,请问有没有人能帮帮我!!
再次编辑
我发现PostgreSQL 9.4的earth_box函数肯定有一些bug,它不能总是得到正确的结果集,我不得不把它改成earth_distance函数并使用多选投影为了使其运行良好,较新的 namedQuery 为:
@NamedQuery(name = "SiteEntity.findBySiteLNR", query = "SELECT s, FUNC('earth_distance', FUNC('ll_to_earth',:positionLatitude, :positionLongitude), FUNC('ll_to_earth',s.siteLatitude,s.siteLongitude)) AS dfcl " +
"FROM SiteEntity s WHERE dfcl < :range ORDER BY dfcl"),
我没有使用 hibernate,而是使用 EclipseLink 和 JPA 2.1,EJB 容器是 Weblogic 12C,EJB 规范 3.1。
我认为提示说明了一切:您需要添加显式类型转换。
您可以通过添加双分号和要将其转换为的类型来实现。即
'-28.175613'::text
或者函数期望的任何内容。
经过大约 4 个小时的努力,我找到了解决方案。主要是,因为它是来自 JPA 的函数调用,所以必须知道一些技巧。
PSQL 语句为:
select * from site s where earth_box(ll_to_earth(-28.175613,153.52578399999993),100000) @> ll_to_earth(s.site_latitude,s.site_longitude);
JPA namedQuery 为:
@NamedQuery(name = "SiteEntity.findByEarthDistance", query = "SELECT s FROM SiteEntity s WHERE FUNC('earth_box', FUNC('ll_to_earth',:positionLatitude, :positionLongitude), :range) > FUNC('ll_to_earth',s.siteLatitude,s.siteLongitude)"),
JPA 中的嵌套函数调用也可以,谢谢!
强烈建议使用 FUNCTION 而不是 FUNC(以前的实现:http://www.eclipse.org/eclipselink/documentation/2.6/jpa/extensions/jpql.htm#func)。 EclipseLink 支持按 FUNCTIONS 排序和分组,但它不适用于 FUNC。
@NamedQuery(name = "SiteEntity.findByEarthDistance", query = "SELECT s FROM SiteEntity s WHERE FUNCTION('earth_box', FUNCTION('ll_to_earth',:positionLatitude, :positionLongitude), :range) > FUNCTION('ll_to_earth',s.siteLatitude,s.siteLongitude)")
@Query(
"""
FROM Place pl
WHERE
FUNCTION('cube_contains',
FUNCTION('earth_box',
FUNCTION('ll_to_earth', :latitude, :longitude),
:radiusInMeters),
FUNCTION('ll_to_earth', pl.latitude, pl.longitude)
) = TRUE
""")
fun getPlacesNear(
pageable: Pageable,
@Param("latitude") latitude: Double,
@Param("longitude") longitude: Double,
@Param("radiusInMeters") radiusInMeters: Int
): Page<Place>
这对寻呼和远程支持非常有效
出于某种奇怪的原因
@Query(
"""
FROM Place pl
WHERE
FUNCTION('ll_to_earth', pl.latitude, pl.longitude)
< FUNCTION('earth_box', FUNCTION('ll_to_earth', :latitude, :longitude), :radiusInMeters)
""")
https://www.postgresql.org/docs/9.5/cube.html#CUBE-GIST-OPERATORS
由于某些奇怪的原因,“<”无法正常工作,因为“<”在 postgres 中没有被正确解释,并给出了错误的结果。
对于 postgres,您需要 spring JPA 无法解释的 '@<' 符号,所以我不得不切换到使用 cube_contains 函数
我本可以使用 native_query = true 但这不会给我分页支持,这就是我切换到 JPA 查询的原因。
所以如果你不需要分页,你可以使用下面的。
@Query(
"""SELECT *, earth_distance(ll_to_earth(:latitude, :longitude), ll_to_earth(latitude, longitude)) as distance
FROM place
WHERE (earth_box(ll_to_earth(:latitude, :longitude), :radiusInMeters) @> ll_to_earth(latitude, longitude))
ORDER BY distance ASC
""", nativeQuery = true)
fun getPlacesNear(
@Param("latitude") latitude: Double,
@Param("longitude") longitude: Double,
@Param("radiusInMeters") radiusInMeters: Int
): List<Place>?