Search code examples
spatialquerydsl

Spatial querydsl - GeometryExpressions. Find entities that range contains given "Point"


Used tools and their versions:

I am using:

  • spring boot 2.2.6
  • hibernate/hibernate-spatial 5.3.10 with dialect set to: org.hibernate.spatial.dialect.mysql.MySQL56SpatialDialect
  • querydsl-spatial 4.2.1
  • com.vividsolutions.jts 1.13
  • jscience 4.3.1

Problem description:

I have an entity that represents medical-clinic:

import com.vividsolutions.jts.geom.Polygon;

@Entity
public class Clinic {

    @Column(name = "range", columnDefinition = "Polygon")
    private Polygon range;
}

The range is a circle calculated earlier based on the clinic's gps-location and radius. It represents the operating area for that clinic. That means that it treats only patients with their home address lying within that circle. Let's assume that above circle, is correct.

My goal (question):

I have a gps point with a patient location: 45.7602322 4.8444941. I would like to find all clinics that are able to treat that patient. That means, to find all the clinics that their range field contains 45.7602322 4.8444941.

My solution (partially correct (I think))

To get it done, I have created a simple "Predicate"/"BooleanExpression":

GeometryExpressions.asGeometry(QClinic.clinic.range)
                .contains(Wkt.fromWkt("Point(45.7602322 4.8444941)"))

and it actualy works, because I can see proper sql query in console:

select (...) where
    ST_Contains(clinic0_.range, ?)=1 limit ?

first binding param: POINT(45.7602322 4.8444941)

But I have two problems with that:

  1. QClinic.clinic.range is marked as "warning" in intellij as: "Unchecked assignment: 'com.querydsl.spatial.jts.JTSPolygonPath' to 'com.querydsl.core.types.Expression<org.geolatte.geom.Geometry'". Yes, in QClinic range is com.querydsl.spatial.jts.JTSPolygonPath
  2. Using debugger and intellij's "evaluate" on the above line (that creates the expression) i can see that there is an error message: "unknown operation with operator CONTAINS and args [clinic.range, POINT(45.7602322 4.8444941)]"

Solution

  • You can ignore the second warning. The spatial specific operations are simply not registered in the serializer used for the toString of the operation. They reside in their own module.

    The first warning indicates that you're mixing up Geolatte and JTS expressions. From your mapping it seems you intend to use JTS. In that case you need to use com.querydsl.spatial.jts.JTSGeometryExpressions instead of com.querydsl.spatial.jts.GeometryExpressions in order to get rid of that warning.