You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于经纬度的地址及距离检索JPQL查询报错,请求修正

修复Spring Data JPA地理距离查询的Having子句错误

你猜的没错,问题确实出在HQL对别名的解析规则以及having子句的使用场景上。咱们一步步来解决:

错误根源

  1. having的使用场景不对:having是用来过滤分组后的结果,必须配合group by一起使用,你这里没有分组操作,直接用having本身就违反了HQL语法。
  2. 别名无法在having中引用:即使有分组,HQL解析器也不允许在having里直接引用select子句中定义的别名(比如你这里的distance),因为解析顺序是先处理where/having,再处理select的别名绑定。

修正方案一:用where替代having,重复距离计算表达式

既然不需要分组,直接用where子句过滤,把距离计算的逻辑完整复制到where里就行:

@Query("Select new com.geolocation.AddressVM(A, " +
        "(" +
        " 6371 * " +
        " acos( " +
        " cos(radians(:lat)) * " +
        " cos(radians(A.geoLocation.latitude)) *" +
        " cos(" +
        " radians(A.geoLocation.longtitude) - radians(:lng)" +
        " ) + " +
        " sin(radians(:lat)) *" +
        " sin(radians(A.geoLocation.latitude))" +
        " ) " +
        ") as distance) " +
        "from #{#entityName} A " +
        "where (" +
        " 6371 * " +
        " acos( " +
        " cos(radians(:lat)) * " +
        " cos(radians(A.geoLocation.latitude)) *" +
        " cos(" +
        " radians(A.geoLocation.longtitude) - radians(:lng)" +
        " ) + " +
        " sin(radians(:lat)) *" +
        " sin(radians(A.geoLocation.latitude))" +
        " ) " +
        ") > :distance")
List<AddressVM> list(@Param("lat") double lat, @Param("lng") double lng, @Param("distance") double distance);

修正方案二:使用子查询(更简洁,避免重复代码)

把计算距离的逻辑放到子查询里,外层再过滤结果,这样代码更易读:

@Query("Select addrWithDistance from (" +
        " Select new com.geolocation.AddressVM(A, " +
        " (" +
        " 6371 * " +
        " acos( " +
        " cos(radians(:lat)) * " +
        " cos(radians(A.geoLocation.latitude)) *" +
        " cos(" +
        " radians(A.geoLocation.longtitude) - radians(:lng)" +
        " ) + " +
        " sin(radians(:lat)) *" +
        " sin(radians(A.geoLocation.latitude))" +
        " ) " +
        ") as distance) " +
        "from #{#entityName} A) addrWithDistance " +
        "where addrWithDistance.distance > :distance")
List<AddressVM> list(@Param("lat") double lat, @Param("lng") double lng, @Param("distance") double distance);

额外提示

  • 确保你的AddressVM有对应的构造器:public AddressVM(Address entity, double distance),否则映射会失败。
  • 如果你的数据库支持地理空间函数(比如PostGIS、MySQL的ST_Distance),可以考虑用原生SQL或者数据库自带的地理函数,性能会比手动计算Haversine公式更好。

内容的提问来源于stack exchange,提问作者dkn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:23:14