存储库本机查询中的 PostgreSQL + Spring Boot JPA 计算属性映射

问题描述 投票:0回答:1

我目前正在编写地理定位应用程序的代码(所以我使用 PostGIS)。我的查询当前按到用户的距离对结果进行排序,并且我想返回每个结果的距离(以米为单位)。

我的存储库代码如下所示(请注意,我正在执行键集分页,因此是 WHERE 条件):

@Query(value = "WITH distance_query AS (" +
        "   SELECT p.*, ST_Distance(p.location, ST_MakePoint(:lng, :lat)) AS distance_in_m " +
        "   FROM places p" +
        ") " +
        "SELECT * FROM distance_query " +
        "WHERE distance_in_m > :lastDistanceInM " +
        "ORDER BY distance_in_m ASC", nativeQuery = true)
List<PlaceDto> findNearbyPlaces(
        double lat,
        double lng,
        double lastDistanceInM
);

我的实体包含一个

@Transient
字段
Double distanceInM
,但查询中的 distance_in_m 未映射到该字段。我的理解是这是预期的,因为
@Transient
用于在映射时完全忽略带注释的字段。

我已经看到了使用

@Formula
的潜在方法,但由于
lat
lng
值是可变的,我认为这行不通。我还想避免重新计算距离(因此在我的原始查询中使用了 CTE)。

有什么方法可以让

distanceInM
字段填充计算值吗?

现在查询工作正常,唯一的问题是

distanceInM
属性未填充。

编辑:

PlaceDto
目前看起来像这样:

@Entity
@Table(name = "places")
public class PlaceDto {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private String id;

    private Date updateDate;
    private String name;
    public Point location;
    private String address;

    @Transient
    public Double distanceInM;

    public PlaceDto() {
    }

    // Getters
}
postgresql spring-boot hibernate spring-data-jpa postgis
1个回答
0
投票

根据您的查询和实体类,下一种解决方案可以满足您的要求,并解决提取所有日期的问题。

首先:

创建一个与本机查询中的

AS
子句中的字段名称匹配的接口投影:

public interface PlaceDtoInterfaceProjection {

  String getId();

  Date getUpdateDate();

  String getName();

  Point getLocation();

  String getAddress();

  Double getDistanceInM();

}

第二个稍微改变一下存储库中的查询:

  @Query(value = "WITH distance_query AS (" +
      "   SELECT p.id AS id, p.update_date AS updateDate, p.name AS name,"
      + " p.location AS location, p.address AS address,"
      + " ST_Distance(p.location, ST_MakePoint(:lng, :lat)) AS distanceInM " +
      "   FROM places p" +
      ") " +
      "SELECT * FROM distance_query " +
      "WHERE distanceInM > :lastDistanceInM " +
      "ORDER BY distanceInM ASC", nativeQuery = true)
  List<PlaceDtoInterfaceProjection> findNearbyPlaces(
      @Param("lat") double lat,
      @Param("lng") double lng,
      @Param("lastDistanceInM") double lastDistanceInM
  );

它会工作得很好,但我不太确定

Point
,顺便说一下,这是最简单的方法,更多细节或替代方法如何提取它,你可以找到spring-data-jpa-dto-native -查询

© www.soinside.com 2019 - 2024. All rights reserved.