Class DistanceHaversineJdbcFunction

java.lang.Object
ch.tocco.nice2.persist.core.api.hibernate.query.AbstractJdbcFunction
ch.tocco.nice2.optional.geolocation.impl.jdbc.DistanceHaversineJdbcFunction
All Implemented Interfaces:
JdbcFunction

@Component public class DistanceHaversineJdbcFunction extends AbstractJdbcFunction

Writes the Haversine function using SQL functions. The function calculates the distance between two points on earth's surface. This can then be used to create queries that filter on distances.

The formula itself:

  RADIUS_EARTH * 2 * ASIN(MIN(1, SQRT(POW(SIN((lat2-lat1) / 2),2) + COS(lat1) * COS(lat2) * POW(SIN((lng2-lng1)/2), 2))))

It needs 4 arguments (exactly) and expects it in the following order:

  latitude1, longitude1, latitude2, longitude2

Where (latitude1, longitude1) name the first points coordinates and (latitude2, longitude2) name the second points coordinates. The coordinates are assumed to be given in RAD.

For example, consider the following query:

   Query q = ctx.compileQuery("find Cities where DISTANCE(pos_lat, pos_lng, :lat, :lng) < :dst");
   Position zurich = new Position(...);
   q.setParameter("pos_lat", zurich.getLatitude());
   q.setParameter("pos_lng", zurich.getLongitude());
   q.setParameter("dst", Distance.kilometer("15").getKm());

This will select all cities that are at maximum 15km away from Zurich (assuming that the "Cities" entity has two fields "pos_lat" and "pos_lng" of respective type.)

  • Field Details

    • EARTH_RADIUS_KM

      public static final BigDecimal EARTH_RADIUS_KM
  • Constructor Details

    • DistanceHaversineJdbcFunction

      public DistanceHaversineJdbcFunction(TypeManager typeManager)
  • Method Details

    • render

      protected void render(JdbcFunctionWriter writer, List<? extends org.hibernate.sql.ast.tree.SqlAstNode> arguments)
      Specified by:
      render in class AbstractJdbcFunction
    • getName

      public String getName()
    • getFunctionArgumentTypeResolver

      public org.hibernate.query.sqm.produce.function.FunctionArgumentTypeResolver getFunctionArgumentTypeResolver(org.hibernate.type.spi.TypeConfiguration typeConfiguration)
      Description copied from interface: JdbcFunction
      Per default StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE is used. Sometimes a more specific function resolver must be defined. For example the third argument of `BIRTHDAYIN` must be a string. Without a custom resolver Hibernate tries to convert "3 days" to a LocalDate which results in an exception.
      Specified by:
      getFunctionArgumentTypeResolver in interface JdbcFunction
      Overrides:
      getFunctionArgumentTypeResolver in class AbstractJdbcFunction
    • validateArguments

      public void validateArguments(jakarta.persistence.criteria.Expression<?>[] arguments) throws JdbcFunctionException
      Throws:
      JdbcFunctionException
    • argumentCount

      public int argumentCount()
      Returns:
      the number of expected arguments.