Haversine Formula for Spring Data JPA

Haversine Formula for Spring Data JPA

I was working on a project where I have to find the nearest stores from the current location within X kilometer distance. I was skeptical if I can deliver the story within the promised timeframe. I googled and found out this cool thing called Haversive Formula. I was able to deliver it way before the expected time. The Haversine formula calculates the shortest distance between two points on a sphere using their latitudes and longitudes measured along the surface. It is important for use in navigation.

I have latitude and longitude stored in the table. The Entity Store looks like:

@Entity
@Table(name = "STORE")
@Getter
@Setter
public class Store {
    @Id
    @GeneratedValue(strategy = GenerationType._IDENTITY_)
    private long id;
    private double latitude;
    private double longitude;
}

Let’s say now we want to find all the stores within a 10-kilometer distance from our current location then using Spring Data JPA repository we can do it as:

public interface StoreRepository extends JpaRepository<Store, Long>{

String HAVERSINE_FORMULA = "(6371 * acos(cos(radians(:latitude)) * cos(radians(s.latitude)) *" +
        " cos(radians(s.longitude) - radians(:longitude)) + sin(radians(:latitude)) * sin(radians(s.latitude))))";

@Query("SELECT s FROM Store s WHERE " + HAVERSINE_FORMULA + " < :distance ORDER BY "+ HAVERSINE_FORMULA + " DESC")
List<Store> findStoresWithInDistance(
@Param("latitude") double latitude,
 @Param("longitude") double longitude,
 @Param("distance") double distanceWithInKM );

The parameters latitude and longitude are your current location values whereas distance represents the distance you want to search within. (10KM in our case).

As you can see, in the Haversine Formula, we have used 6371. This is the value for the radius of the earth in KM. If you want to search using miles then you need to change it to 3961 from 6371.

Thanks a lot for reading my article :)