简体   繁体   中英

calculating distance between two coordinates SQL + Criteria Builder

So in my code i want to be able to check what coordinates are in range with some reference coordinates. At the begining i was using some native SQL query like:

  @Query(
          value = "SELECT * FROM event " +
                  "   inner join event_location location on location.id = event.location_id\n" +
                  "  where Round( ST_Distance_Sphere(\n" +
                  "    Point(?1 , ?2 )," +
                  "    Point(location.longtitude , location.latitude ), 4326), 2) <= ?3",
          nativeQuery = true)
  List<Event> findAllEventsInRange(double longtitude, double latitude, String range);

It was working pretty well, but now i would like to use Specification with criteria builder. And to be honest i dont know how i can write condition after where keyword.

Can anyone let me know how i can do it?

EDIT: Entities are definied. And i already created specification which is for now joining two tables - event and event location:

public static Specification<Event> filter(Search search){
return (root, cq, cb) -> {
      Predicate location = null;

      List<Predicate> result = new ArrayList<>();

      if(search.getLat() != null && search.getLng() != null && search.getRange() != null) {
         Join<Event,EventLocation> join = root.join("eventLocation", JoinType.LEFT);
            }

            return cb.and(result.toArray(new Predicate[result.size()]));
        };
    }

And now i need to create a proper predicate which will do the same thing as statement after WHERE. I know there is function on criteria builder which can be used for some native sql function but not sure how i can use it in my case and combine with different other sql functions as well.

You need to use the generic function invocation syntax for this, which would look something like the following:

public static Specification<Event> filter(Search search){
    return (root, cq, cb) -> {
      Predicate location = null;

      List<Predicate> result = new ArrayList<>();

      if(search.getLat() != null && search.getLng() != null && search.getRange() != null) {
         Join<Event,EventLocation> join = root.join("eventLocation", JoinType.LEFT);
         result.add(
           cb.le(
             cb.function("Round", String.class,
               cb.function("ST_Distance_Sphere", String.class, 
                 cb.function("Point", String.class, 
                   cb.literal(search.getLat()),
                   cb.literal(search.getLng())
                 ),
                 cb.function("Point", String.class, 
                   join.get("longtitude"),
                   join.get("latitude ")
                 ),
                 cb.literal(4326)
               ),
               cb.literal(2)
             ),
             cb.literal(search.getRange())
           )
         );
      }
  
      return cb.and(result.toArray(new Predicate[result.size()]));
   };
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM