【问题标题】:Using QueryDSL in order to query a database for close distance points使用 QueryDSL 查询数据库中的近距离点
【发布时间】:2023-03-08 20:01:01
【问题描述】:

我的应用程序中有以下实体:

  • Member
  • FamilyAdvertisment
  • Address

Member 实体中:

@OneToOne(cascade=CascadeType.ALL)
    private Address address;
...
@OneToMany(fetch = FetchType.LAZY, mappedBy = "member")
private List<Advertisement> advertisements;

Advertisement 实体中:

@NotNull
@ManyToOne(fetch = FetchType.LAZY)
private Member member;

完整的Address实体:

@Entity
public class Address {

    private String formattedAddress;
    private double latitude;
    private double longitude;
}

我正在尝试查找其成员的地址在所需地址 20KM 范围内的所有 FamilyAdvertisement 实例。

这是我想出的:

QFamilyAdvertisement qFamilyAdvertisement = QFamilyAdvertisement.familyAdvertisement;

NumberPath<Double> lat = qFamilyAdvertisement.member.address.latitude;//NPE
NumberPath<Double> lng = qFamilyAdvertisement.member.address.longitude;
NumberPath<Double> distance = null;
NumberExpression<Double> formula = 
        (acos(cos(radians(Expressions.constant(requiredAddress.getLatitude())))
        .multiply(cos(radians(lat))
        .multiply(cos(radians(lng).subtract(radians(Expressions.constant(requiredAddress.getLongitude())))
        .add(sin(radians(Expressions.constant(requiredAddress.getLatitude())))
        .multiply(sin(radians(lat))))))))
        .multiply(Expressions.constant(6371)));

List<FamilyAdvertisement> foundFamilyAdvertisements = from(qFamilyAdvertisement.member.address).where(formula.as(distance).lt(20)).list(qFamilyAdvertisement);

但是,当我不断获得 NPE 时,我似乎错误地使用了 NumberPath 类。谁能帮我正确查询?

编辑:我已将我的 FamilyAdvertisement 实体更改如下:

@NotNull
@ManyToOne(fetch = FetchType.LAZY)
@QueryInit("address")
private Member member;

我现在得到以下异常:

java.lang.IllegalArgumentException: Only root paths are allowed for joins : familyAdvertisement.member.address
    com.mysema.query.DefaultQueryMetadata.ensureRoot(DefaultQueryMetadata.java:208)
    com.mysema.query.DefaultQueryMetadata.validateJoin(DefaultQueryMetadata.java:132)
    com.mysema.query.DefaultQueryMetadata.addJoin(DefaultQueryMetadata.java:118)
    com.mysema.query.DefaultQueryMetadata.addJoin(DefaultQueryMetadata.java:110)
    com.mysema.query.support.QueryMixin.from(QueryMixin.java:161)
    com.mysema.query.jpa.JPQLQueryBase.from(JPQLQueryBase.java:96)
    com.mysema.query.jpa.impl.JPAQuery.from(JPAQuery.java:30)
    org.springframework.data.jpa.repository.support.Querydsl.createQuery(Querydsl.java:88)
    org.springframework.data.jpa.repository.support.QueryDslRepositorySupport.from(QueryDslRepositorySupport.java:94)
    com.bignibou.repository.FamilyAdvertisementRepositoryImpl.performFamilyAdvertisementSearch(FamilyAdvertisementRepositoryImpl.java:64)

第 64 行是这一行:

List<FamilyAdvertisement> foundFamilyAdvertisements = from(qFamilyAdvertisement.member.address).where(formula.as(distance).lt(20)).list(qFamilyAdvertisement);

知道现在出了什么问题吗?

edit2:我忘了提到FamilyAdvertisement 扩展了Advertisement 并且member 变量在Advertisement 中。

edit3:这是我尝试使用 QueryDSL 重现的 SQL:

select * from family_advertisement a inner join member m
on a.member = m.id
where m.address
in (
SELECT id 
FROM address where 
 6371 * 
acos( cos( radians(48.8558966) ) 
* cos( radians( latitude ) ) 
* cos( radians( longitude ) - radians(2.3622728) ) 
+ sin( radians(48.8558966) )
* sin( radians( latitude ) )
) < 20);

我尝试过这样的事情:

List<FamilyAdvertisement> foundFamilyAdvertisements = from(qFamilyAdvertisement).where(qFamilyAdvertisement.member.address.in(

                new JPASubQuery().from(QAddress.address).where(formula.lt(20)))

                ).list(qFamilyAdvertisement);

上面给出了公式,但我不确定如何在 QueryDSL 中表达不相关的子查询,尤其是上面的 in 运算符似乎有问题......

edit4

现在可以使用以下子查询:

List<FamilyAdvertisement> foundFamilyAdvertisements = 
        from(qFamilyAdvertisement).where(qFamilyAdvertisement.member.address.in(new JPASubQuery().from(QAddress.address).where(formula.lt(20)).list(QAddress.address))).list(qFamilyAdvertisement);

【问题讨论】:

  • 我试过你的方法,甚至用相同的gps创建了地址。然而,没有返回任何结果。

标签: geolocation querydsl


【解决方案1】:

这条路径对于急切初始化来说太长了

qFamilyAdvertisement.member.address.latitude;

请在此处阅读有关 Querydsl http://www.querydsl.com/static/querydsl/3.1.0/reference/html/ch03s04.html#d0e1699 中路径初始化的更多信息

【讨论】:

  • 嗨蒂莫。我已经修改了我的实体,现在我得到了一个:IllegalArgumentException: Only root paths are allowed for joins : familyAdvertisement.member.address。我已经编辑了我的帖子。
  • from 参数需要是根路径、变量。
  • 我正在尝试使用子查询,但 in 方法不会像在 sql 中那样采用子查询。知道如何获得正确的 Timo 吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-23
  • 2015-10-02
  • 1970-01-01
  • 1970-01-01
  • 2019-04-09
相关资源
最近更新 更多