【问题标题】:SQL to JPQL - haversine formulaSQL 到 JPQL - 正弦公式
【发布时间】:2018-08-08 12:48:34
【问题描述】:

我有这个 SQL 查询,它从点表返回位置并按距离(以公里为单位)对它们进行排序。 该查询在 SQL 中工作,但我在将其转换为 JPQL 时遇到了一些困难。 我暂时使用静态值以使其更易于阅读。

SQL - 有效

SELECT DISTINCT *,( 6371 * acos( cos( radians(60.1733) ) * cos( radians( spot.spot_latitude )) 
        * cos( radians(spot.spot_longitude) - radians(24.941)) + sin(radians(60.1733)) 
        * sin( radians(spot.spot_latitude)))) AS distance 

    FROM spot

    WHERE spot_id = spot_id 
        HAVING distance < 10    
        ORDER BY distance

JPQL - 不起作用

SELECT DISTINCT s, ( 6371 * acos( cos( radians(60.1733) ) * cos( radians( spot.spot_latitude ))
        * cos( radians(spot.spot_longitude) - radians(24.941)) + sin(radians(60.1733))
        * sin( radians(spot.spot_latitude)))) AS distance 

    FROM spot  

    WHERE s.spot_id = s.spot_id
        HAVING distance < 10
        ORDER BY s.distance

JPQL 引发两个具有根本原因的异常:

    A MultiException has 2 exceptions.  They are:
1. org.eclipse.persistence.exceptions.PersistenceUnitLoadingException: 
Exception Description: An exception was thrown while searching for persistence archives with ClassLoader: ParallelWebappClassLoader
  context: skatebayBackend
  delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@2f2c9b19

Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [skatebay_pu] failed.
Internal Exception: Exception [EclipseLink-7158] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Error encountered when building the @NamedQuery [Spot.getSpotsInMyArea] from entity class [class org.eclipse.persistence.internal.jpa.metadata.queries.NamedQueryMetadata].
Internal Exception: java.lang.ClassCastException: org.eclipse.persistence.jpa.jpql.parser.NullExpression cannot be cast to org.eclipse.persistence.jpa.jpql.parser.IdentificationVariable
2. java.lang.IllegalStateException: Unable to perform operation: create on rest.SpotApi

【问题讨论】:

  • JPQL 没有很多可用的函数(acos、cos、弧度、sin 等)。 JPQL!= SQL。一些 JPA 提供程序(例如 DataNucleus)确实允许它们,请参阅 datanucleus.org:15080/products/accessplatform_5_1/jpa/… 。不知道 EclipseLink。使用地理空间 java 类型显然会更容易
  • @BillyFrost 这就是我所害怕的,但感谢您提供的信息 :)
  • Eclipselink 文档似乎是这个 wiki.eclipse.org/EclipseLink/UserGuide/JPA/… 在您编写它们时不允许它们。您可能必须在它们周围使用FUNCTIONFUNC;不漂亮

标签: java mysql sql jpa jpql


【解决方案1】:

JPQL 适用于实体而不适用于数据库表。您在这里至少有两个选择:

确保您已将实体映射到表并为您的查询使用正确的语法。但是 JPQL 提供的可能性比 SQL 少。

因此,也许在您的情况下,创建本机查询会更容易,然后您就可以使用普通的 sql。

Query query = getEntityManager().createNativeQuery("select * from table...");
List<Object> string = query.getResultList();

【讨论】:

  • 这也是我发现的,它适用于 NativeQuery。额外的问题是,有没有办法将其作为注释,如@NamedQueries。希望我的所有查询都在它自己的实体类中
  • 您可以对实体使用注解@NamedNativeQuery(name = "queryName", query = "sql"),然后将其称为命名查询Query query = getEntityManager().createNamedQuery("queryName") ;
【解决方案2】:

您在 JPQL 的 where 子句中使用了别名 s,请改为这样做。

SELECT DISTINCT s, ( 6371 * acos( cos( radians(60.1733) ) * cos( radians( spot.spot_latitude ))
        * cos( radians(spot.spot_longitude) - radians(24.941)) + sin(radians(60.1733))
        * sin( radians(spot.spot_latitude)))) AS distance 

    FROM spot AS s

    WHERE s.spot_id = s.spot_id
        HAVING distance < 10
        ORDER BY s.distance

【讨论】:

    猜你喜欢
    • 2016-12-30
    • 2016-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多