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

在JPA方法中能否在@Formula注解内使用@Param参数?

解决Spring Data JPA中@Formula注解无法识别方法参数的问题

问题原因

你在@Formula中使用的:lat、:lon参数无法被Spring Data JPA识别,是因为**@Formula是实体类上的静态计算字段定义**,它默认只能引用实体自身的字段或全局参数,无法直接关联仓库方法的动态参数。Spring Data JPA在校验方法参数时,会认为这些参数没有被实际查询语句使用,从而抛出错误。

可行解决方案

方案1:改用@Query原生SQL查询(推荐)

直接在仓库方法上使用@Query编写原生PostgreSQL查询,这样方法参数能被正确识别,同时可以直接计算距离并按距离排序:

@Query(value = "SELECT ca.*, point(:lat, :lon) <@> point(ca.longitude, ca.latitude) AS distance " +
               "FROM club_address ca " +
               "ORDER BY distance ASC", 
       nativeQuery = true)
List<ClubAddress> getClubAddressClosestBy(@Param("lat") double latitude, @Param("lon") double longitude);

如果需要同时获取距离值,可以创建一个DTO类(比如ClubAddressWithDistance),通过构造函数映射查询结果:

// DTO类示例
public class ClubAddressWithDistance {
    private ClubAddress clubAddress;
    private Double distance;

    public ClubAddressWithDistance(ClubAddress clubAddress, Double distance) {
        this.clubAddress = clubAddress;
        this.distance = distance;
    }

    // 此处添加getter、setter方法
}

修改仓库方法为JPQL查询(需确保Hibernate能解析PostgreSQL的point操作):

@Query(value = "SELECT new com.yourpackage.ClubAddressWithDistance(ca, point(:lat, :lon) <@> point(ca.longitude, ca.latitude)) " +
               "FROM ClubAddress ca " +
               "ORDER BY point(:lat, :lon) <@> point(ca.longitude, ca.latitude) ASC")
List<ClubAddressWithDistance> getClubAddressClosestBy(@Param("lat") double latitude, @Param("lon") double longitude);

方案2:通过实体Transient字段传递参数(不推荐)

如果一定要保留@Formula,可以在实体类中添加两个@Transient字段存储动态参数,再在@Formula中引用,但这种方式需要手动设置参数,灵活性差:

@Entity
@Table(name = "club_address")
public class ClubAddress {
    // 原有实体字段...

    @Transient
    private Double currentLat;

    @Transient
    private Double currentLon;

    @Formula("(SELECT point(current_lat, current_lon) <@> (point(longitude, latitude)::point) FROM club_address ca WHERE ca.id = id)")
    private Double distance;

    // 此处添加currentLat、currentLon、distance的getter、setter方法
}

这种方式在Spring Data JPA仓库方法中无法直接传递参数,需要先构造实体并设置参数后再执行查询,实用性不高,仅作参考。

内容的提问来源于stack exchange,提问作者Sebastian G.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 23:00:55