【发布时间】:2016-11-29 15:40:46
【问题描述】:
我正在使用带有 JPA 和 Hibernate 5.2.1 和 MySQL 数据库的 Java 8。
我有一张带有用户 GPS 坐标的表格:
第 1 行:
LAT_1: 28.85, LONG_1: -25.766667
LAT_2: 27.15, LONG_2: -26.133333
第 2 行:
LAT_1: 27.25, LONG_1: -26.234567
LAT_2: 28.98, LONG_2: -25.456666
然后我也有一个 user selected 坐标值:
LAT_USER: 27.22, LONG_USER: -26.89998
我需要数据库查询中的结果集以返回按距最近 GPS 点的距离排序(asc)的行。
在本例中,距离LAT_USER & LONG_USER 最近的 GPS 点是:
对于第 1 行:
LAT_2 & LONG_2
对于第 2 行:
LAT_1 & LONG_1
这可能吗?
到目前为止,这是我的基本代码:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(entityClass);
// from
Root<T> from = criteriaQuery.from(entityClass);
criteriaQuery.select(from);
// order by
List<Order> order = new ArrayList<Order>();
// ????
criteriaQuery.orderBy(order);
List<T> results = (List<T>) entityManager.createQuery(criteriaQuery).setFirstResult(firstResult)
.setMaxResults(maxResults).getResultList();
return results;
我会感谢任何人的帮助。
谢谢
更新:
我的表结构如下(我还有其他的连接表,但这是为了简单起见):
---------- ------------------- -----------
| EMPLOYEE | | EMPLOYEE_LOCATION | | LOCATION |
---------- ------------------- -----------
|ID | |EMP_ID | | ID |
| | |LOC_ID | | LATITUDE |
| | | | | LONGITUDE |
---------- ------------------- -----------
我的Employee模型对象有位置:
@OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
@JoinTable
(
name="employee_location",
joinColumns={ @JoinColumn(name="EMP_ID", referencedColumnName="ID") },
inverseJoinColumns={ @JoinColumn(name="LOC_ID", referencedColumnName="ID", unique=true) }
)
private Set<Location> locations;
我明白要实现我需要的,我需要对数据库进行Haversine formula 计算,因为我需要用计算结果对结果集进行排序。
我知道这会导致一个相当复杂的查询,因为它需要找到最低距离,并按此排序。
SELECT e.id,
( 6371 * acos( cos( radians(37) ) * cos( radians( l.LATITUDE) ) * cos( radians( l.LONGITUDE) - radians(-122) ) + sin( radians(37) ) * sin( radians( l.LATITUDE) ) ) ) AS distance
FROM www.employee AS e
inner join
www.employee_location as el
on e.id=el.EMP_ID
inner join
www.location as l
on el.LOC_ID=l.ID
order by DISTANCE
这会正确返回 ID 和 DISTANCE,但它会返回 3 个 EMPLOYEES,因为该 EMPLOYEE 有 3 个 LOCATIONS。当它在 JPA 中连接时(如上),这将返回 1 个 EMPLOYEE 和 3 个 LOCATIONS。
有谁知道我如何最好将其保留在 JPA 对象中并为 Haversine formula 添加自定义 SQL(要简单得多,因为我还有其他联接。或者这不可能吗?)。然后,我需要按该员工的最低 LOCATION 的距离进行排序。
更新
我会用这样的东西:
select ID, min(distance) as mindistance from (
select e.ID,
( 6371 * acos( cos( radians(37) ) * cos( radians( o.LATITUDE) ) * cos( radians( o.LONGITUDE) - radians(-122) ) + sin( radians(37) ) * sin( radians( o.LATITUDE) ) ) ) AS distance
from
www.employee as e
inner join
www.employee_location as eo
on e.id=eo.EMP_ID
inner join
www.location as o
on eo.LOC_ID=o.ID ) xxx
group by ID
order by mindistance;
【问题讨论】:
-
您可能在这里寻找的公式称为 Haversine 公式,它计算球体上两点之间的距离。您可能希望在数据库中进行此计算,并且您可能还希望对数据库进行空间分区。
-
谢谢蒂姆。我同意,我需要对数据库进行计算,因为它是按顺序进行的。我正在尝试使用 SQL/JPQL/HQL 进行此计算。我遇到的困难是每一行都知道要使用哪个坐标,以及计算本身。我目前正在努力,希望也能在这里得到一些帮助。
-
查看here,了解有关Haversine 公式的讨论。
-
谢谢,看看....
-
只是一个问题:为什么不使用几何列类型(例如 JTS 点)存储信息?那么您将拥有可以完成所有这些工作的地理空间方法
标签: java sql hibernate jpa spatial