SAP Home Learn Build Integrate Model Operate Extend with AI ConnectTutorial navigator Knowledge Graph API Devtoberfest Developer Advocates App Space

Manage my Account SAP Devs YouTube ↗ Learnings ↗ Community ↗ Provide Feedback ↗
Logout
โคข Open full site

Add Advanced Geospatial Processing with Hibernate

Make use of the SAP HANA geospatial engine via Hibernate Spatial.

Overview

🎓 intermediate 20 min. SAP Hana, Express EditionIntermediateJavaSAP HANAExpress Edition

You will learn

  • โœ”How to make use of the SAP HANA geospatial engine via Hibernate Spatial
Unknown U Unknown November 1, 2022
Created by August 14, 2018
Contributors

Prerequisites

Steps

Motivation

The initial implementation of the application not leveraging geospatial processing capabilities has some severe disadvantages.

Intro

Here is a query taken from the file IncidentRepository.java in the directory src/main/java/com/sap/hana/hibernate/sample/repositories that loads the police incidents within a certain distance around a given location:

Java
query = this.em.createQuery(
    "select i from Incident i "
        + "where i.category in :category "
        + "  and i.date between :dateFrom and :dateTo "
        + "  and i.x between (x(:location) - (cast(:distance as double) / 111319)) "
        + "    and (x(:location) + (cast(:distance as double) / 111319)) "
        + "  and i.y between (y(:location) - (cast(:distance as double) / 111319)) "
        + "    and (y(:location) + (cast(:distance as double) / 111319)) "
        + "order by i.date desc",
    Incident.class );

Some of the disadvantages of this query are:

  • The query is somewhat long and hard to understand.
  • The query uses a constant for converting a distance in meters to degrees which is less accurate the farther the given location is from the earth’s equator.
  • For simplicity, the query retrieves the incidents whose x and y coordinates are within +/- the distance which means that the area of the incidents is a rectangle rather than a circle.

All of these disadvantages can be addressed by using SAP HANA’s built-in geospatial engine.


Step 1 Use geospatial functions for the incident list
โ€”

Open the file IncidentRepository.java from the directory src/main/java/com/sap/hana/hibernate/sample/repositories.

In all queries, replace the part starting with

Code
and i.y between

until the last

Code
(cast(:distance as double) / 111319))

with a geospatial function. The function to be used is dwithin which calculates whether a location is within a given distance of another location.

Before

Java
query = this.em.createQuery(
    "select i from Incident i "
        + "where i.category in :category "
        + "  and i.date between :dateFrom and :dateTo "
        + "  and i.x between (x(:location) - (cast(:distance as double) / 111319)) "
        + "    and (x(:location) + (cast(:distance as double) / 111319)) "
        + "  and i.y between (y(:location) - (cast(:distance as double) / 111319)) "
        + "    and (y(:location) + (cast(:distance as double) / 111319)) "
        + "order by i.date desc",
    Incident.class );

After

Java
query = this.em.createQuery(
    "select i from Incident i "
        + "where i.category in :category "
        + "  and i.date between :dateFrom and :dateTo "
        + "  and dwithin(i.location, :location, :distance) = true "
        + "order by i.date desc",
    Incident.class );

As you can immediately see, the query is now much easier to read, doesn’t contain any magic constants and performs the correct calculations taking into account the earth’s geometry.

Do this adjustment for all 4 queries in the file.

Java
public Page<Incident> findByLocationNear(Point<G2D> location, Distance distance, Date dateFrom, Date dateTo,
    List<String> category, Pageable pageable) {
  TypedQuery<Incident> query;
  if ( category == null || category.isEmpty() ) {
    query = this.em.createQuery(
        "select i from Incident i "
            + "where i.date between :dateFrom and :dateTo "
            + "  and dwithin(i.location, :location, :distance) = true "
            + "order by i.date desc",
        Incident.class );
  }
  else {
    query = this.em.createQuery(
        "select i from Incident i "
            + "where i.category in :category "
            + "  and i.date between :dateFrom and :dateTo "
            + "  and dwithin(i.location, :location, :distance) = true "
            + "order by i.date desc",
        Incident.class );
    query.setParameter( "category", category );
  }

  query.setParameter( "dateFrom", dateFrom );
  query.setParameter( "dateTo", dateTo );
  query.setParameter( "location", location );
  query.setParameter( "distance", distance );

  query.setFirstResult( (int) pageable.getOffset() );
  query.setMaxResults( pageable.getPageSize() );

  Query countQuery;
  if ( category == null || category.isEmpty() ) {
    countQuery = this.em.createQuery(
        "select count(i) from Incident i "
            + "where i.date between :dateFrom and :dateTo "
            + "  and dwithin(i.location, :location, :distance) = true " );

  }
  else {
    countQuery = this.em.createQuery(
        "select count(i) from Incident i "
            + "where i.category in :category "
            + "  and i.date between :dateFrom and :dateTo "
            + "  and dwithin(i.location, :location, :distance) = true " );
    countQuery.setParameter( "category", category );
  }

  countQuery.setParameter( "dateFrom", dateFrom );
  countQuery.setParameter( "dateTo", dateTo );
  countQuery.setParameter( "location", location );
  countQuery.setParameter( "distance", distance );

  long count = ( (Long) countQuery.getSingleResult() ).longValue();

  return new PageImpl<>( query.getResultList(), pageable, count );
}

Save the IncidentRepository.java file.

Step 2 Use geospatial functions for the incident heat map
+
Step 3 Deploy the application
+
Step 4 Learn about Spatial Reference Systems (SRS)
+
Step 5 Enable the SRS transformation
+
Step 6 Change the SRS used for the incident list
+
Step 7 Change the SRS used for the incident heat map
+
Step 8 Deploy the application
+

Resources

Discussion

Share feedback on this tutorial or join the conversation in SAP Community.

Submit detailed feedback Discuss in Community
Steps
Step 1 of 8
1. Use geospatial functions for the incident list 2. Use geospatial functions for the incident heat map 3. Deploy the application 4. Learn about Spatial Reference Systems (SRS) 5. Enable the SRS transformation 6. Change the SRS used for the incident list 7. Change the SRS used for the incident heat map 8. Deploy the application

Learn more →