Updates Spatial Documentation
This commit is contained in:
parent
cc10cbebc2
commit
5c8c794553
|
@ -43,6 +43,13 @@ ext {
|
|||
'jdbc.user' : 'hibernate_orm_test',
|
||||
'jdbc.pass' : '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.
|
||||
====
|
||||
|
||||
.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.
|
||||
That is the purpose of the "BasicTypeRegistry key(s)" column in the previous tables.
|
||||
|
||||
|
|
|
@ -7,20 +7,33 @@
|
|||
=== Overview
|
||||
|
||||
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.
|
||||
|
||||
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,
|
||||
yet, not all databases support all the functions defined by Hibernate Spatial.
|
||||
It supports most of the functions described by the OGC Simple Feature Specification. Supported databases are: Oracle 10g/11g,
|
||||
PostgreSql/PostGIS, MySQL, Microsoft SQL Server and H2/GeoDB.
|
||||
|
||||
Hibernate Spatial uses the Java Topology Suite (JTS) as its geometry model.
|
||||
JTS is an implementation of the OpenGIS Simple Features Implementation Specification for SQLv. 1.1 (SFS).
|
||||
This specification is implemented in most RDBMS with spatial data support.
|
||||
It is also a direct precursor to SQL/MM Part 3: Spatial (ISO/IEC 13249-3).
|
||||
Spatial data types are not part of the Java standard library, and they are absent from the JDBC specification.
|
||||
Over the years http://tsusiatsoftware.net/jts/main.html[JTS] has emerged the _de facto_ standard to fill this gap. JTS is
|
||||
an implementation of the https://portal.opengeospatial.org/files/?artifact_id=829[Simple Feature Specification (SFS)]. Many databases
|
||||
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 makes a subset of these functions available in HQL and in the Criteria Query API.
|
||||
Hibernate Spatial supports two different geometry models: http://tsusiatsoftware.net/jts/main.html[JTS] and
|
||||
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]]
|
||||
=== 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.
|
||||
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"]
|
||||
: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.
|
||||
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]]
|
||||
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
|
||||
[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).
|
||||
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.
|
||||
====
|
||||
|
||||
`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::
|
||||
The dialect `SqlServer2008Dialect` supports the `GEOMETRY` type in SQL Server 2008 and later.
|
||||
|
||||
|
@ -214,18 +208,20 @@ jts_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.
|
||||
|
||||
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]]
|
||||
.Type mapping
|
||||
====
|
||||
[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]]
|
||||
.Creating a Point
|
||||
|
@ -236,18 +232,8 @@ include::{sourcedir}/SpatialTest.java[tags=spatial-types-point-creation-example]
|
|||
----
|
||||
====
|
||||
|
||||
Hibernate generates the following SQL statement:
|
||||
|
||||
[[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 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-query-example]]
|
||||
.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.Id;
|
||||
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.spatial.dialect.postgis.PostgisDialect;
|
||||
|
||||
|
@ -17,9 +16,12 @@ import org.hibernate.testing.RequiresDialect;
|
|||
import org.junit.Test;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
//tag::spatial-types-mapping-example[]
|
||||
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;
|
||||
|
||||
|
@ -31,6 +33,8 @@ import static org.hibernate.userguide.util.TransactionUtil.doInJPA;
|
|||
@RequiresDialect(PostgisDialect.class)
|
||||
public class SpatialTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
GeometryFactory geometryFactory = new GeometryFactory();
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
|
@ -41,19 +45,16 @@ public class SpatialTest extends BaseEntityManagerFunctionalTestCase {
|
|||
@Test
|
||||
public void test() {
|
||||
Long addressId = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
try {
|
||||
//tag::spatial-types-point-creation-example[]
|
||||
Event event = new Event();
|
||||
event.setId( 1L);
|
||||
event.setName( "Hibernate ORM presentation");
|
||||
event.setLocation( (Point) new WKTReader().read( "POINT(10 5)"));
|
||||
//tag::spatial-types-point-creation-example[]
|
||||
Event event = new Event();
|
||||
event.setId( 1L);
|
||||
event.setName( "Hibernate ORM presentation");
|
||||
Point point = geometryFactory.createPoint( new Coordinate( 10, 5 ) );
|
||||
event.setLocation( point );
|
||||
|
||||
entityManager.persist( event );
|
||||
//end::spatial-types-point-creation-example[]
|
||||
return event.getId();
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
entityManager.persist( event );
|
||||
//end::spatial-types-point-creation-example[]
|
||||
return event.getId();
|
||||
});
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
@ -64,63 +65,62 @@ public class SpatialTest extends BaseEntityManagerFunctionalTestCase {
|
|||
});
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
try {
|
||||
//tag::spatial-types-query-example[]
|
||||
Event event = entityManager.createQuery(
|
||||
"select e " +
|
||||
"from Event e " +
|
||||
"where within(e.location, :filter) = true", Event.class)
|
||||
.setParameter("filter", new WKTReader().read( "POLYGON((1 1,20 1,20 20,1 20,1 1))"))
|
||||
.getSingleResult();
|
||||
//end::spatial-types-query-example[]
|
||||
Coordinate coordinate = event.getLocation().getCoordinate();
|
||||
assertEquals( 10.0d, coordinate.getOrdinate( Coordinate.X), 0.1);
|
||||
assertEquals( 5.0d, coordinate.getOrdinate( Coordinate.Y), 0.1);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
Coordinate [] coordinates = new Coordinate[] {
|
||||
new Coordinate(1,1), new Coordinate(20,1), new Coordinate(20,20),
|
||||
new Coordinate(1,20), new Coordinate(1,1)
|
||||
};
|
||||
//tag::spatial-types-query-example[]
|
||||
Polygon window = geometryFactory.createPolygon( coordinates );
|
||||
Event event = entityManager.createQuery(
|
||||
"select e " +
|
||||
"from Event e " +
|
||||
"where within(e.location, :window) = true", Event.class)
|
||||
.setParameter("window", window)
|
||||
.getSingleResult();
|
||||
//end::spatial-types-query-example[]
|
||||
Coordinate coordinate = event.getLocation().getCoordinate();
|
||||
assertEquals( 10.0d, coordinate.getOrdinate( Coordinate.X), 0.1);
|
||||
assertEquals( 5.0d, coordinate.getOrdinate( Coordinate.Y), 0.1);
|
||||
});
|
||||
}
|
||||
|
||||
//tag::spatial-types-mapping-example[]
|
||||
@Entity(name = "Event")
|
||||
public static class Event {
|
||||
//tag::spatial-types-mapping-example[]
|
||||
@Entity(name = "Event")
|
||||
public static class Event {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
@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
|
||||
//end::spatial-types-mapping-example[]
|
||||
public Long getId() {
|
||||
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[]
|
||||
//Getters and setters are omitted for brevity
|
||||
//end::spatial-types-mapping-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
//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