hibernate PostgreSQL + Sping Boot JPA在存储库原生查询中计算属性Map

2w2cym1i  于 2023-10-23  发布在  PostgreSQL
关注(0)|答案(1)|浏览(131)

我目前正在编写一个地理定位应用程序的代码(所以我使用的是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没有Map到这个字段。我的理解是,这是预期的,因为@Transient是用来在Map时完全忽略注解字段的。
我看到过使用@Formula的潜在方法,但由于latlng的值是可变的,我认为这不会起作用。我还想避免重新计算距离(因此在我的原始查询中使用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
}
0tdrvxhp

0tdrvxhp1#

根据您的查询和实体类,下一个解决方案可以满足您的要求,并解决提取所有日期的问题。
首先:
在原生查询中创建一个与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-queries
P.S.关于Point,你可以从数据库中分别提取xy,然后构建它,但我认为你知道如何在自己的。

相关问题