Updates Spatial Documentation
This commit is contained in:
parent
1bd940b47e
commit
7ad1c59876
|
@ -43,6 +43,13 @@ ext {
|
||||||
'jdbc.user' : 'hibernate_orm_test',
|
'jdbc.user' : 'hibernate_orm_test',
|
||||||
'jdbc.pass' : 'hibernate_orm_test',
|
'jdbc.pass' : 'hibernate_orm_test',
|
||||||
'jdbc.url' : 'jdbc:mariadb://localhost/hibernate_orm_test'
|
'jdbc.url' : 'jdbc:mariadb://localhost/hibernate_orm_test'
|
||||||
]
|
],
|
||||||
|
postgis : [
|
||||||
|
'db.dialect' : 'org.hibernate.spatial.dialect.postgis.PostgisDialect',
|
||||||
|
'jdbc.driver': 'org.postgresql.Driver',
|
||||||
|
'jdbc.user' : 'hibernate_orm_test',
|
||||||
|
'jdbc.pass' : 'hibernate_orm_test',
|
||||||
|
'jdbc.url' : 'jdbc:postgresql:hibernate_orm_test'
|
||||||
|
],
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,20 @@ To use these hibernate-java8 types just add the `hibernate-java8` dependency to
|
||||||
See <<basic-datetime>> for more about Java 8 Date/Time types.
|
See <<basic-datetime>> for more about Java 8 Date/Time types.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
.BasicTypes added by hibernate-spatial
|
||||||
|
[cols=",,,",options="header",]
|
||||||
|
|=================================================================================================
|
||||||
|
|Hibernate type (org.hibernate.spatial package) |JDBC type |Java type |BasicTypeRegistry key(s)
|
||||||
|
|JTSGeometryType |depends on the dialect | com.vividsolutions.jts.geom.Geometry |jts_geometry, or the classname of Geometry or any of its subclasses
|
||||||
|
|GeolatteGeometryType |depends on the dialect | org.geolatte.geom.Geometry |geolatte_geometry, or the classname of Geometry or any of its subclasses
|
||||||
|
|=================================================================================================
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
To use these hibernate-spatial types just must add the `hibernate-spatial` dependency to your classpath _and_ use a the `org.hibernate.spatial.SpatialDialect`.
|
||||||
|
See <<spatial>> for more about spatial types.
|
||||||
|
====
|
||||||
|
|
||||||
These mappings are managed by a service inside Hibernate called the `org.hibernate.type.BasicTypeRegistry`, which essentially maintains a map of `org.hibernate.type.BasicType` (a `org.hibernate.type.Type` specialization) instances keyed by a name.
|
These mappings are managed by a service inside Hibernate called the `org.hibernate.type.BasicTypeRegistry`, which essentially maintains a map of `org.hibernate.type.BasicType` (a `org.hibernate.type.Type` specialization) instances keyed by a name.
|
||||||
That is the purpose of the "BasicTypeRegistry key(s)" column in the previous tables.
|
That is the purpose of the "BasicTypeRegistry key(s)" column in the previous tables.
|
||||||
|
|
||||||
|
|
|
@ -7,20 +7,33 @@
|
||||||
=== Overview
|
=== Overview
|
||||||
|
|
||||||
Hibernate Spatial was originally developed as a generic extension to Hibernate for handling geographic data.
|
Hibernate Spatial was originally developed as a generic extension to Hibernate for handling geographic data.
|
||||||
Since 5.0, Hibernate Spatial is now part of Hibernate ORM project,
|
Since 5.0, Hibernate Spatial is now part of the Hibernate ORM project,
|
||||||
and it allows you to deal with geographic data in a standardized way.
|
and it allows you to deal with geographic data in a standardized way.
|
||||||
|
|
||||||
Hibernate Spatial provides a standardized, cross-database interface to geographic data storage and query functions.
|
Hibernate Spatial provides a standardized, cross-database interface to geographic data storage and query functions.
|
||||||
It supports most of the functions described by the OGC Simple Feature Specification, and the supported databases are: Oracle 10g/11g, PostgreSql/PostGIS, MySQL, Microsoft SQL Server and H2/GeoDB,
|
It supports most of the functions described by the OGC Simple Feature Specification. Supported databases are: Oracle 10g/11g,
|
||||||
yet, not all databases support all the functions defined by Hibernate Spatial.
|
PostgreSql/PostGIS, MySQL, Microsoft SQL Server and H2/GeoDB.
|
||||||
|
|
||||||
Hibernate Spatial uses the Java Topology Suite (JTS) as its geometry model.
|
Spatial data types are not part of the Java standard library, and they are absent from the JDBC specification.
|
||||||
JTS is an implementation of the OpenGIS Simple Features Implementation Specification for SQLv. 1.1 (SFS).
|
Over the years http://tsusiatsoftware.net/jts/main.html[JTS] has emerged the _de facto_ standard to fill this gap. JTS is
|
||||||
This specification is implemented in most RDBMS with spatial data support.
|
an implementation of the https://portal.opengeospatial.org/files/?artifact_id=829[Simple Feature Specification (SFS)]. Many databases
|
||||||
It is also a direct precursor to SQL/MM Part 3: Spatial (ISO/IEC 13249-3).
|
on the other hand implement the SQL/MM - Part 3: Spatial Data specification - a related, but broader specification. The biggest difference is that
|
||||||
|
SFS is limited to 2D geometries in the projected plane (although JTS supports 3D coordinates), whereas
|
||||||
|
SQL/MM supports 2-, 3- or 4-dimensional coordinate spaces.
|
||||||
|
|
||||||
The SFS specification defines a set of functions on geometries.
|
Hibernate Spatial supports two different geometry models: http://tsusiatsoftware.net/jts/main.html[JTS] and
|
||||||
Hibernate Spatial makes a subset of these functions available in HQL and in the Criteria Query API.
|
https://github.com/GeoLatte/geolatte-geom[geolatte-geom]. As already mentioned, JTS is the _de facto_
|
||||||
|
standard. Geolatte-geom (also written by the lead developer of Hibernate Spatial) is a more recent library that
|
||||||
|
supports many features specified in SQL/MM but not available in JTS (such as support for 4D geometries, and support for extended WKT/WKB formats).
|
||||||
|
Geolatte-geom also implements encoders/decoders for the database native types. Geolatte-geom has good interoperability with
|
||||||
|
JTS. Converting a Geolatte `geometry` to a JTS `geometry, for instance, doesn't require copying of the coordinates.
|
||||||
|
It also delegates spatial processing to JTS.
|
||||||
|
|
||||||
|
Whether you use JTS or Geolatte-geom, Hibernate spatial maps the database spatial types to your geometry model of choice. It will, however,
|
||||||
|
always use Geolatte-geom to decode the database native types.
|
||||||
|
|
||||||
|
Hibernate Spatial also makes a number of spatial functions available in HQL and in the Criteria Query API. These functions are
|
||||||
|
specified in both SQL/MM as SFS, and are commonly implemented in databases with spatial support (see <<spatial-configuration-dialect-features>>)
|
||||||
|
|
||||||
[[spatial-configuration]]
|
[[spatial-configuration]]
|
||||||
=== Configuration
|
=== Configuration
|
||||||
|
@ -65,7 +78,9 @@ So, for instance, instead of using the `PostgreSQL82Dialect`, we use the Hiberna
|
||||||
====
|
====
|
||||||
|
|
||||||
Not all databases support all the functions defined by Hibernate Spatial.
|
Not all databases support all the functions defined by Hibernate Spatial.
|
||||||
The table below provides an overview of the functions provided by each database.
|
The table below provides an overview of the functions provided by each database. If the function is defined in the
|
||||||
|
https://portal.opengeospatial.org/files/?artifact_id=829[Simple Feature Specification], the description references the
|
||||||
|
relevant section.
|
||||||
|
|
||||||
:yes: icon:check[role="green"]
|
:yes: icon:check[role="green"]
|
||||||
:no: icon:times[role="red"]
|
:no: icon:times[role="red"]
|
||||||
|
@ -115,14 +130,7 @@ For Postgis from versions 1.3 and later, the best dialect to use is `org.hiberna
|
||||||
+
|
+
|
||||||
This translates the HQL spatial functions to the Postgis SQL/MM-compliant functions.
|
This translates the HQL spatial functions to the Postgis SQL/MM-compliant functions.
|
||||||
For older, pre v1.3 versions of Postgis, which are not SQL/MM compliant, the dialect `org.hibernate.spatial.dialect.postgis.PostgisNoSQLMM` is provided.
|
For older, pre v1.3 versions of Postgis, which are not SQL/MM compliant, the dialect `org.hibernate.spatial.dialect.postgis.PostgisNoSQLMM` is provided.
|
||||||
+
|
|
||||||
This dialect depends on the JDBC extensions in postgis.jar (see the http://postgis.net/docs/postgis_installation.html#id336398[Postgis documentation]).
|
|
||||||
|
|
||||||
[IMPORTANT]
|
|
||||||
====
|
|
||||||
Beware of classpath problems in a Java EE containers where the JDBC drivers live in a different classpath than the Postgis JDBC extensions and/or Hibernate Spatial.
|
|
||||||
For JBoss, some users found https://gist.github.com/bjornharrtell/3054462[this post] helpful.
|
|
||||||
====
|
|
||||||
[[spatial-configuration-dialect-mysql]]
|
[[spatial-configuration-dialect-mysql]]
|
||||||
MySQL::
|
MySQL::
|
||||||
There are several dialects for MySQL:
|
There are several dialects for MySQL:
|
||||||
|
@ -162,7 +170,7 @@ the fully-qualified classname for the Connection finder for this Dialect (see be
|
||||||
.The `ConnectionFinder` interface
|
.The `ConnectionFinder` interface
|
||||||
[NOTE]
|
[NOTE]
|
||||||
====
|
====
|
||||||
The `SDOGeometryType` requires access to an `OracleConnection` object when converting a geometry to SDO_GEOMETRY.
|
The `SDOGeometryType` requires access to an `OracleConnection` object wehen converting a geometry to SDO_GEOMETRY.
|
||||||
In some environments, however, the `OracleConnection` is not available (e.g. because a Java EE container or connection pool proxy wraps the connection object in its own `Connection` implementation).
|
In some environments, however, the `OracleConnection` is not available (e.g. because a Java EE container or connection pool proxy wraps the connection object in its own `Connection` implementation).
|
||||||
A `ConnectionFinder` knows how to retrieve the `OracleConnection` from the wrapper or proxy Connection object that is passed into prepared statements.
|
A `ConnectionFinder` knows how to retrieve the `OracleConnection` from the wrapper or proxy Connection object that is passed into prepared statements.
|
||||||
|
|
||||||
|
@ -175,20 +183,6 @@ If not, you can provide your own implementation of this interface on the class p
|
||||||
Note that implementations must be thread-safe and have a default no-args constructor.
|
Note that implementations must be thread-safe and have a default no-args constructor.
|
||||||
====
|
====
|
||||||
|
|
||||||
`hibernate.spatial.ogc_strict`::: true to use the OGC-compliant functions on SDO_GEOMETRY (see below)
|
|
||||||
.OGC Compliance Setting
|
|
||||||
[NOTE]
|
|
||||||
====
|
|
||||||
The Oracle Spatial dialect can be configured to run in either OGC strict or non-strict mode.
|
|
||||||
In OGC strict mode, the Open Geospatial compliant functions of Oracle Spatial are used in spatial operations (they exists in Oracle 10g, but are not documented).
|
|
||||||
In non-strict mode, the usual Oracle Spatial functions are used directly, and mimic the OGC semantics.The default is OGC strict mode.
|
|
||||||
You can change this to non-strict mode by setting the hibernate.spatial.ogc_strict property to false.
|
|
||||||
|
|
||||||
Note that changing from strict to non-strict mode changes the semantics of the spatial operation.
|
|
||||||
We have attempted to implement the OGC semantics as well we could using the standard Oracle Spatial operators, but this was not possible in all cases.
|
|
||||||
On the plus side, non-strict mode should be faster in most cases.
|
|
||||||
====
|
|
||||||
|
|
||||||
SQL Server::
|
SQL Server::
|
||||||
The dialect `SqlServer2008Dialect` supports the `GEOMETRY` type in SQL Server 2008 and later.
|
The dialect `SqlServer2008Dialect` supports the `GEOMETRY` type in SQL Server 2008 and later.
|
||||||
|
|
||||||
|
@ -214,18 +208,20 @@ jts_geometry::
|
||||||
geolatte_geometry::
|
geolatte_geometry::
|
||||||
Handled by `org.hibernate.spatial.GeolatteGeometryType`, it maps a database geometry column type to an `org.geolatte.geom.Geometry` entity property type.
|
Handled by `org.hibernate.spatial.GeolatteGeometryType`, it maps a database geometry column type to an `org.geolatte.geom.Geometry` entity property type.
|
||||||
|
|
||||||
The following entity uses the `jts_geometry` to map the PostgreSQL geometry type to a `com.vividsolutions.jts.geom.Point`.
|
It suffices to declare a property as either a JTS or an Geolatte-geom `Geometry` and Hibernate Spatial will map it using the
|
||||||
|
relevant type.
|
||||||
|
|
||||||
|
Here is an example using JTS:
|
||||||
[[spatial-types-mapping-example]]
|
[[spatial-types-mapping-example]]
|
||||||
.Type mapping
|
.Type mapping
|
||||||
====
|
====
|
||||||
[source, JAVA, indent=0]
|
[source, JAVA, indent=0]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/SpatialTest.java[tags=spatial-types-mapping-example]
|
include::{sourcedir}/SpatialTest.java[tags=spatial-types-mapping-example, indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
When creating such entity:
|
We can now treat spatial geometries like any other type.
|
||||||
|
|
||||||
[[spatial-types-point-creation-example]]
|
[[spatial-types-point-creation-example]]
|
||||||
.Creating a Point
|
.Creating a Point
|
||||||
|
@ -236,18 +232,8 @@ include::{sourcedir}/SpatialTest.java[tags=spatial-types-point-creation-example]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
Hibernate generates the following SQL statement:
|
Spatial Dialects defines many query functions that are available both in HQL and JPQL queries. Below we show how we
|
||||||
|
could use the `within` function to find all objects within a given spatial extent or window.
|
||||||
[[spatial-types-point-creation-example]]
|
|
||||||
.Creating a Point
|
|
||||||
====
|
|
||||||
[source, SQL, indent=0]
|
|
||||||
----
|
|
||||||
include::{extrasdir}/spatial-types-point-creation-example.sql[]
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
Hibernate Spatial defines many query functions that are available both in HQL and JPQL queries.
|
|
||||||
|
|
||||||
[[spatial-types-query-example]]
|
[[spatial-types-query-example]]
|
||||||
.Querying the geometry
|
.Querying the geometry
|
||||||
|
@ -258,13 +244,3 @@ include::{sourcedir}/SpatialTest.java[tags=spatial-types-query-example]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
This JPQL query generates the following SQL statement:
|
|
||||||
|
|
||||||
[[spatial-types-sql-query-example]]
|
|
||||||
.Underlying SQL query
|
|
||||||
====
|
|
||||||
[source, SQL, indent=0]
|
|
||||||
----
|
|
||||||
include::{extrasdir}/spatial-types-sql-query-example.sql[]
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.userguide.spatial;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
|
||||||
import org.hibernate.annotations.Type;
|
|
||||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
import org.hibernate.spatial.dialect.postgis.PostgisDialect;
|
import org.hibernate.spatial.dialect.postgis.PostgisDialect;
|
||||||
|
|
||||||
|
@ -17,9 +16,12 @@ import org.hibernate.testing.RequiresDialect;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import com.vividsolutions.jts.geom.Coordinate;
|
import com.vividsolutions.jts.geom.Coordinate;
|
||||||
|
//tag::spatial-types-mapping-example[]
|
||||||
import com.vividsolutions.jts.geom.Point;
|
import com.vividsolutions.jts.geom.Point;
|
||||||
import com.vividsolutions.jts.io.ParseException;
|
|
||||||
import com.vividsolutions.jts.io.WKTReader;
|
//end::spatial-types-mapping-example[]
|
||||||
|
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||||
|
import com.vividsolutions.jts.geom.Polygon;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
@ -31,6 +33,8 @@ import static org.hibernate.userguide.util.TransactionUtil.doInJPA;
|
||||||
@RequiresDialect(PostgisDialect.class)
|
@RequiresDialect(PostgisDialect.class)
|
||||||
public class SpatialTest extends BaseEntityManagerFunctionalTestCase {
|
public class SpatialTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
GeometryFactory geometryFactory = new GeometryFactory();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
return new Class<?>[] {
|
return new Class<?>[] {
|
||||||
|
@ -41,19 +45,16 @@ public class SpatialTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
Long addressId = doInJPA( this::entityManagerFactory, entityManager -> {
|
Long addressId = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
try {
|
//tag::spatial-types-point-creation-example[]
|
||||||
//tag::spatial-types-point-creation-example[]
|
Event event = new Event();
|
||||||
Event event = new Event();
|
event.setId( 1L);
|
||||||
event.setId( 1L);
|
event.setName( "Hibernate ORM presentation");
|
||||||
event.setName( "Hibernate ORM presentation");
|
Point point = geometryFactory.createPoint( new Coordinate( 10, 5 ) );
|
||||||
event.setLocation( (Point) new WKTReader().read( "POINT(10 5)"));
|
event.setLocation( point );
|
||||||
|
|
||||||
entityManager.persist( event );
|
entityManager.persist( event );
|
||||||
//end::spatial-types-point-creation-example[]
|
//end::spatial-types-point-creation-example[]
|
||||||
return event.getId();
|
return event.getId();
|
||||||
} catch (ParseException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
@ -64,63 +65,62 @@ public class SpatialTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
});
|
});
|
||||||
|
|
||||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
try {
|
Coordinate [] coordinates = new Coordinate[] {
|
||||||
//tag::spatial-types-query-example[]
|
new Coordinate(1,1), new Coordinate(20,1), new Coordinate(20,20),
|
||||||
Event event = entityManager.createQuery(
|
new Coordinate(1,20), new Coordinate(1,1)
|
||||||
"select e " +
|
};
|
||||||
"from Event e " +
|
//tag::spatial-types-query-example[]
|
||||||
"where within(e.location, :filter) = true", Event.class)
|
Polygon window = geometryFactory.createPolygon( coordinates );
|
||||||
.setParameter("filter", new WKTReader().read( "POLYGON((1 1,20 1,20 20,1 20,1 1))"))
|
Event event = entityManager.createQuery(
|
||||||
.getSingleResult();
|
"select e " +
|
||||||
//end::spatial-types-query-example[]
|
"from Event e " +
|
||||||
Coordinate coordinate = event.getLocation().getCoordinate();
|
"where within(e.location, :window) = true", Event.class)
|
||||||
assertEquals( 10.0d, coordinate.getOrdinate( Coordinate.X), 0.1);
|
.setParameter("window", window)
|
||||||
assertEquals( 5.0d, coordinate.getOrdinate( Coordinate.Y), 0.1);
|
.getSingleResult();
|
||||||
}
|
//end::spatial-types-query-example[]
|
||||||
catch (ParseException e) {
|
Coordinate coordinate = event.getLocation().getCoordinate();
|
||||||
throw new RuntimeException(e);
|
assertEquals( 10.0d, coordinate.getOrdinate( Coordinate.X), 0.1);
|
||||||
}
|
assertEquals( 5.0d, coordinate.getOrdinate( Coordinate.Y), 0.1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//tag::spatial-types-mapping-example[]
|
//tag::spatial-types-mapping-example[]
|
||||||
@Entity(name = "Event")
|
@Entity(name = "Event")
|
||||||
public static class Event {
|
public static class Event {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Type(type = "jts_geometry")
|
private Point location;
|
||||||
private Point location;
|
|
||||||
|
|
||||||
//Getters and setters are omitted for brevity
|
//Getters and setters are omitted for brevity
|
||||||
//end::spatial-types-mapping-example[]
|
//end::spatial-types-mapping-example[]
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point getLocation() {
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLocation(Point location) {
|
|
||||||
this.location = location;
|
|
||||||
}
|
|
||||||
//tag::spatial-types-mapping-example[]
|
|
||||||
}
|
}
|
||||||
//end::spatial-types-mapping-example[]
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocation(Point location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
//tag::spatial-types-mapping-example[]
|
||||||
|
}
|
||||||
|
//end::spatial-types-mapping-example[]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue