I am new to Hibernate Spatial, and am trying to perform a simple query of objects within a given radius. I've created a number of entries in my database with properties corresponding to a latitude and longitude, using data from Google Maps and other sources. This property is defined like this in my Entity class:
@Column
@Type(type = "org.hibernate.spatial.GeometryType")
private Point coordinates = null;
I'm now trying to figure out how to do a search of all entity objects that have coordinates that fall within a radius of x kilometers from a given point. For example, I'd like to find objects that fall within a 50 kilometer radius of the point (12.34567, -76.54321). However, I can't find any examples or tutorials that would explain how to do this in Hibernate Spatial.
Can anyone give me any information on how a query like this can be constructed?
See this resource for a tutorial with "Spatial Queries", which a special dialect and the JTS library (Open Source).
Basically you do the following (copy/paste from the referenced page):
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import util.JPAUtil;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.Date;
import java.util.List;
.......
private List find(String wktFilter) {
Geometry filter = wktToGeometry(wktFilter);
EntityManager em = JPAUtil.createEntityManager();
em.getTransaction().begin();
Query query = em.createQuery("select e from Event e where within(e.location, :filter) = true", Event.class);
query.setParameter("filter", filter);
return query.getResultList();
}
private Geometry wktToGeometry(String wktPoint) {
WKTReader fromText = new WKTReader();
Geometry geom = null;
try {
geom = fromText.read(wktPoint);
} catch (ParseException e) {
throw new RuntimeException("Not a WKT string:" + wktPoint);
}
return geom;
}
For generating a circle, see this resource (search for "Arcs, Circles and Curves"). Again a copy/paste from there:
//this method replaces the above wktToGeometry() method
private static Geometry createCircle(double x, double y, final double RADIUS) {
GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
shapeFactory.setNumPoints(32);
shapeFactory.setCentre(new Coordinate(x, y));//there are your coordinates
shapeFactory.setSize(RADIUS * 2);//this is how you set the radius
return shapeFactory.createCircle();
}
Besides you always have the workaround, in which to add some additional fields ( mapped withinsertable=false, updatable=false
) to map to the same columns used by the org.hibernate.spatial.GeometryType
and then use them in your query. For computing the distance, check the euclidian distance formula.