2016-07-26 23 views
0

Ich benutze Java 8 mit JPA und Hibernate 5.2.1 und MySQL Datenbank.Java JPA Order By mit GPS Koordinaten

Ich habe eine Tabelle mit Benutzern GPS-Koordinaten:

Reihe 1:

LAT_1: 28.85, LONG_1: -25.766667 
LAT_2: 27.15, LONG_2: -26.133333 

Row 2:

LAT_1: 27.25, LONG_1: -26.234567 
LAT_2: 28.98, LONG_2: -25.456666 

Dann habe ich einen Benutzer ausgewählten Wert der Koordinaten auch:

LAT_USER: 27.22, LONG_USER: -26.89998 

Ich brauche das Ergebnis aus der Datenbankabfrage festgelegt in Zeilen zurückgeben nach Entfernung von dem nächsten GPS-Punkt bestellt (auf).

In diesem Beispiel wird der nächste GPS-Punkt zu LAT_USER & LONG_USER sein:

Für Reihe 1:

LAT_2 & LONG_2 

Für Row 2:

LAT_1 & LONG_1 

Ist das möglich ?

Hier ist meine Basis-Code so weit:

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; 

Ich würde jede Hilfe zu schätzen wissen.

Dank

UPDATE:

ist Meine Tabellenstruktur wie folgt (I anderen Tabellen beitreten haben, aber dies ist der Einfachheit halber):

----------  ------------------- ----------- 
| EMPLOYEE | | EMPLOYEE_LOCATION | | LOCATION | 
----------  ------------------- ----------- 
|ID  | |EMP_ID    | | ID  | 
|   | |LOC_ID    | | LATITUDE | 
|   | |     | | LONGITUDE | 
----------  ------------------- ----------- 

Mein Mitarbeiter Modell Objekt hat Positionen:

@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; 

Ich verstehe, um zu erreichen, was ich brauche, muss ich die Haversine formula Berechnung auf der Datenbank tun, weil ich die Ergebnismenge mit dem Berechnungsergebnis bestellen muss.

Ich weiß, dass dies zu einer ziemlich komplizierten Abfrage führen wird, weil es die niedrigste Entfernung finden muss, und durch diese bestellen.

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 

Dies gibt die ID und die Entfernung richtig, jedoch gibt es 3 Mitarbeiter, weil es drei Standorte für diese Mitarbeiter. Wenn es in JPA verdrahtet ist (wie oben), wird 1 EMPLOYEE mit 3 LOCATIONS zurückgegeben.

Wer weiß, wie ich dies vorzugsweise in JPA-Objekten behalten und benutzerdefinierte SQL für die Haversine formula hinzufügen könnte (viel einfacher, weil ich andere Joins habe. Oder ist das nicht möglich?). Dann muss ich nach der Entfernung des niedrigsten Standorts für diesen Angestellten bestellen.

UPDATE

werde ich so etwas wie folgt verwenden:

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

Die Formel, nach der Sie hier wahrscheinlich suchen, ist etwas, das die _Haversine_ Formel genannt wird, die den Abstand zwischen zwei Punkten auf einer Kugel berechnet. Möglicherweise möchten Sie diese Berechnung in Ihrer Datenbank ausführen und möchten möglicherweise auch Ihre Datenbank räumlich partitionieren. –

+0

Danke Tim. Ich stimme zu, ich brauche die Berechnung in der Datenbank, weil sie die Reihenfolge erledigt. Ich versuche, SQL/JPQL/HQL zu verwenden, um diese Berechnung durchzuführen. Die Schwierigkeit, die ich habe, ist für jede Reihe zu wissen, welche Koordinaten zu verwenden, sowie die Berechnung selbst. Ich arbeite gerade daran und werde hoffentlich auch hier Hilfe bekommen. – Richard

+0

Schauen Sie [hier] (http://stackoverflow.com/questions/574691/mysql-great-circle-distance-haversine-formula) für eine Diskussion der Haversine-Formel. –

Antwort

0

Ich glaube, Sie haben zwei Möglichkeiten

  1. Verwenden Sie die spatial support in MySql
  2. Verwenden Sie die spatial support in Hibernate-Suche (sitzt auf Lucene)

Für Option 1, dann ist es wahrscheinlich, dass Sie für diese Hibernate Unterstützung nicht so haben ich vermute, Sie Session.createSQLQuery(...) benötigen und/oder Restrictions.sqlRestriction(...)

Meine persönliche Präferenz für die Option 1 ist, wie die Lucene-Index verwalten können addieren Sie Komplexität

+0

Danke Lance, werde ich mir das ansehen. – Richard

+0

Lance, wenn ich räumliche Unterstützung verwende, hält es die Daten korrekt (d. H. Als Geometriepunkte), aber das löst immer noch nicht mein Problem, glaube ich nicht? Ich muss in der Lage sein, den niedrigsten von n Punkten zu finden und damit zu sortieren. – Richard

+0

Ich denke, Hibernate ist einer der größten Zeitfresser in der Java-Welt. Wenn nicht zu spät, schlage ich vor, dass Sie alle zusammen überwintern und zu [mybatis] wechseln (http://www.mybatis.org/mybatis-3/) –