我正在使用Java 8和JPA以及Hibernate 5.2.1和MySQL数据库。
我有一张用户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
然后我也有一个用户选择坐标值:
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 |
---------- ------------------- -----------
我的员工模型对象有位置:
@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;
答案 0 :(得分:0)
我认为你有两个选择
对于选项1,您可能无法获得hibernate支持,因此我猜测您需要Session.createSQLQuery(...)和/或Restrictions.sqlRestriction(...)
我个人喜欢选项1,因为管理lucene索引会增加复杂性