diff --git a/hibernate-spatial/databases/mysql56/matrix.gradle b/hibernate-spatial/databases/mysql56/matrix.gradle new file mode 100644 index 0000000000..ec110dbc6e --- /dev/null +++ b/hibernate-spatial/databases/mysql56/matrix.gradle @@ -0,0 +1,24 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +jdbcDependency "mysql:mysql-connector-java:5.1.15" diff --git a/hibernate-spatial/databases/mysql56/resources/hibernate.properties b/hibernate-spatial/databases/mysql56/resources/hibernate.properties new file mode 100644 index 0000000000..d1b46022b4 --- /dev/null +++ b/hibernate-spatial/databases/mysql56/resources/hibernate.properties @@ -0,0 +1,42 @@ +# +# Hibernate, Relational Persistence for Idiomatic Java +# +# Copyright (c) 2011, Red Hat Inc. or third-party contributors as +# indicated by the @author tags or express copyright attribution +# statements applied by the authors. All third-party contributions are +# distributed under license by Red Hat Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# Lesser General Public License, as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this distribution; if not, write to: +# Free Software Foundation, Inc. +# 51 Franklin Street, Fifth Floor +# Boston, MA 02110-1301 USA +# + +hibernate.dialect org.hibernate.spatial.dialect.mysql.MySQL56SpatialDialect +hibernate.connection.driver_class com.mysql.jdbc.Driver +hibernate.connection.url jdbc:mysql://172.16.1.130/test +hibernate.connection.username HBS +hibernate.connection.password HBS + + +hibernate.connection.pool_size 5 + +hibernate.show_sql true +hibernate.format_sql true + +hibernate.max_fetch_depth 5 + +hibernate.cache.region_prefix hibernate.test +hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory + + diff --git a/hibernate-spatial/databases/mysql5_innodb/resources/hibernate.properties b/hibernate-spatial/databases/mysql5_innodb/resources/hibernate.properties index f7bbebe512..5365b14238 100644 --- a/hibernate-spatial/databases/mysql5_innodb/resources/hibernate.properties +++ b/hibernate-spatial/databases/mysql5_innodb/resources/hibernate.properties @@ -24,7 +24,7 @@ hibernate.test.new_metadata_mappings = true -hibernate.dialect org.hibernate.spatial.dialect.mysql.MySQL5SpatialInnoDBDialect +hibernate.dialect org.hibernate.spatial.dialect.mysql.MySQL5InnoDBSpatialDialect hibernate.connection.driver_class com.mysql.jdbc.Driver hibernate.connection.url jdbc:mysql://localhost/testhbs diff --git a/hibernate-spatial/databases/oracle11g_spatial/resources/hibernate.properties b/hibernate-spatial/databases/oracle11g_spatial/resources/hibernate.properties index 1d3b4e37bb..a62a6f0376 100644 --- a/hibernate-spatial/databases/oracle11g_spatial/resources/hibernate.properties +++ b/hibernate-spatial/databases/oracle11g_spatial/resources/hibernate.properties @@ -28,6 +28,9 @@ hibernate.connection.url jdbc:oracle:thin:@oracle11g.geovise.com:1521/orcl11g.ge hibernate.connection.username HBS hibernate.connection.password HBS +## uncommenting this will fail a unit test!! +#hibernate.spatial.ogc_strict false + hibernate.connection.pool_size 5 hibernate.show_sql true diff --git a/hibernate-spatial/hibernate-spatial.gradle b/hibernate-spatial/hibernate-spatial.gradle index 7970f53c9e..a0a243e89c 100644 --- a/hibernate-spatial/hibernate-spatial.gradle +++ b/hibernate-spatial/hibernate-spatial.gradle @@ -22,8 +22,6 @@ apply plugin: 'java' apply plugin: 'hibernate-matrix-testing' -//apply plugin: org.hibernate.build.gradle.testing.matrix.MatrixTestingPlugin - dependencies { compile(project(':hibernate-core')) compile([group: 'postgresql', name: 'postgresql', version: '8.4-701.jdbc4']) @@ -35,6 +33,7 @@ dependencies { } + testCompile(libraries.junit) testCompile(project(':hibernate-testing')) testCompile([group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4']) diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/HibernateSpatialConfiguration.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/HibernateSpatialConfiguration.java new file mode 100644 index 0000000000..9c67430c02 --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/HibernateSpatialConfiguration.java @@ -0,0 +1,69 @@ +package org.hibernate.spatial; + +import org.hibernate.spatial.dialect.oracle.ConnectionFinder; + +/** + * A global configuration object that is is used by + * some Dialects during construction. + * + * @author Karel Maesen, Geovise BVBA + * creation-date: 8/16/13 + */ +public class HibernateSpatialConfiguration { + + private static final Log LOG = LogFactory.make(); + private Boolean isOgcStrict = Boolean.TRUE; + private ConnectionFinder connectionFinder; + + /** + * Holds the configuration for Hibernate Spatial dialects. + */ + public HibernateSpatialConfiguration() { + } + + /** + * Creates a Configuration for Hibernate spatial + * + * @param ogcStrict true for OGC Strict mode + * @param connectionFinder the fully-qualified Class name for the {@code ConnectionFinder} + */ + public HibernateSpatialConfiguration(Boolean ogcStrict, ConnectionFinder connectionFinder) { + if ( ogcStrict != null ) { + this.isOgcStrict = ogcStrict; + LOG.info( String.format( "Setting OGC_STRICT mode for Oracle Spatial dialect to %s.", ogcStrict ) ); + } + if ( connectionFinder != null ) { + this.connectionFinder = connectionFinder; + LOG.info( + String.format( + "Using ConnectionFinder implementation: %s (only relevant for Oracle Spatial dialect).", + connectionFinder.getClass().getCanonicalName() + ) + ); + } + } + + public Boolean isOgcStrictMode() { + return isOgcStrict; + } + + public ConnectionFinder getConnectionFinder() { + return connectionFinder; + } + + /** + * Collects the property names for Hibernate Spatial configuration properties. + */ + public static class AvailableSettings { + /** + * Determines whether or nog to use the OracleSpatial10gDialect in OGC_STRICT mode or not (values: true or false) + */ + public static final String OGC_STRICT = "hibernate.spatial.ogc_strict"; + /** + * The canonical class name to use as Oracle ConnectionFinder implementation. + */ + public static final String CONNECTION_FINDER = "hibernate.spatial.connection_finder"; + } + + +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/criterion/DWithinExpression.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/criterion/DWithinExpression.java index 910ef7812d..aae59b1370 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/criterion/DWithinExpression.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/criterion/DWithinExpression.java @@ -30,6 +30,7 @@ import org.hibernate.criterion.Criterion; import org.hibernate.engine.spi.TypedValue; import org.hibernate.spatial.SpatialDialect; import org.hibernate.spatial.SpatialFunction; +import org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect; import org.hibernate.type.StandardBasicTypes; /** @@ -71,9 +72,14 @@ public class DWithinExpression implements Criterion { @Override public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { + final SpatialDialect spatialDialect = ExpressionUtil.getSpatialDialect( criteriaQuery, SpatialFunction.dwithin ); + TypedValue typedDistanceValue = new TypedValue( StandardBasicTypes.DOUBLE, distance ); + if ( spatialDialect instanceof OracleSpatial10gDialect ) { + typedDistanceValue = new TypedValue( StandardBasicTypes.STRING, "distance=" + distance ); + } return new TypedValue[] { criteriaQuery.getTypedValue( criteria, propertyName, geometry ), - new TypedValue( StandardBasicTypes.DOUBLE, distance ) + typedDistanceValue }; } } diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBDialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBDialect.java index a92847d22b..0e4747de08 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBDialect.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/h2geodb/GeoDBDialect.java @@ -39,50 +39,6 @@ import org.hibernate.type.StandardBasicTypes; */ public class GeoDBDialect extends H2Dialect implements SpatialDialect { - /* - Contents of GeoDB's spatial registration script (geodb.sql): - - CREATE ALIAS AddGeometryColumn for "geodb.GeoDB.AddGeometryColumn" - CREATE ALIAS CreateSpatialIndex for "geodb.GeoDB.CreateSpatialIndex" - CREATE ALIAS DropGeometryColumn for "geodb.GeoDB.DropGeometryColumn" - CREATE ALIAS DropGeometryColumns for "geodb.GeoDB.DropGeometryColumns" - CREATE ALIAS DropSpatialIndex for "geodb.GeoDB.DropSpatialIndex" - CREATE ALIAS EnvelopeAsText for "geodb.GeoDB.EnvelopeAsText" - CREATE ALIAS GeometryType for "geodb.GeoDB.GeometryType" - CREATE ALIAS ST_Area FOR "geodb.GeoDB.ST_Area" - CREATE ALIAS ST_AsEWKB FOR "geodb.GeoDB.ST_AsEWKB" - CREATE ALIAS ST_AsEWKT FOR "geodb.GeoDB.ST_AsEWKT" - CREATE ALIAS ST_AsHexEWKB FOR "geodb.GeoDB.ST_AsHexEWKB" - CREATE ALIAS ST_AsText FOR "geodb.GeoDB.ST_AsText" - CREATE ALIAS ST_BBOX FOR "geodb.GeoDB.ST_BBox" - CREATE ALIAS ST_Buffer FOR "geodb.GeoDB.ST_Buffer" - CREATE ALIAS ST_Centroid FOR "geodb.GeoDB.ST_Centroid" - CREATE ALIAS ST_Crosses FOR "geodb.GeoDB.ST_Crosses" - CREATE ALIAS ST_Contains FOR "geodb.GeoDB.ST_Contains" - CREATE ALIAS ST_DWithin FOR "geodb.GeoDB.ST_DWithin" - CREATE ALIAS ST_Disjoint FOR "geodb.GeoDB.ST_Disjoint" - CREATE ALIAS ST_Distance FOR "geodb.GeoDB.ST_Distance" - CREATE ALIAS ST_Envelope FOR "geodb.GeoDB.ST_Envelope" - CREATE ALIAS ST_Equals FOR "geodb.GeoDB.ST_Equals" - CREATE ALIAS ST_GeoHash FOR "geodb.GeoDB.ST_GeoHash" - CREATE ALIAS ST_GeomFromEWKB FOR "geodb.GeoDB.ST_GeomFromEWKB" - CREATE ALIAS ST_GeomFromEWKT FOR "geodb.GeoDB.ST_GeomFromEWKT" - CREATE ALIAS ST_GeomFromText FOR "geodb.GeoDB.ST_GeomFromText" - CREATE ALIAS ST_GeomFromWKB FOR "geodb.GeoDB.ST_GeomFromWKB" - CREATE ALIAS ST_Intersects FOR "geodb.GeoDB.ST_Intersects" - CREATE ALIAS ST_IsEmpty FOR "geodb.GeoDB.ST_IsEmpty" - CREATE ALIAS ST_IsSimple FOR "geodb.GeoDB.ST_IsSimple" - CREATE ALIAS ST_IsValid FOR "geodb.GeoDB.ST_IsValid" - CREATE ALIAS ST_MakePoint FOR "geodb.GeoDB.ST_MakePoint" - CREATE ALIAS ST_MakeBox2D FOR "geodb.GeoDB.ST_MakeBox2D" - CREATE ALIAS ST_Overlaps FOR "geodb.GeoDB.ST_Overlaps" - CREATE ALIAS ST_SRID FOR "geodb.GeoDB.ST_SRID" - CREATE ALIAS ST_SetSRID FOR "geodb.GeoDB.ST_SetSRID" - CREATE ALIAS ST_Simplify FOR "geodb.GeoDB.ST_Simplify" - CREATE ALIAS ST_Touches FOR "geodb.GeoDB.ST_Touches" - CREATE ALIAS ST_Within FOR "geodb.GeoDB.ST_Within" - CREATE ALIAS Version FOR "geodb.GeoDB.Version" - */ /** @@ -103,9 +59,12 @@ public class GeoDBDialect extends H2Dialect implements SpatialDialect { ); // Register functions that operate on spatial types - // NOT YET AVAILABLE IN GEODB - // registerFunction("dimension", new StandardSQLFunction("dimension", - // Hibernate.INTEGER)); + registerFunction( + "dimension", new StandardSQLFunction( + "ST_Dimension", + StandardBasicTypes.INTEGER + ) + ); registerFunction( "geometrytype", new StandardSQLFunction( "GeometryType", StandardBasicTypes.STRING @@ -117,11 +76,7 @@ public class GeoDBDialect extends H2Dialect implements SpatialDialect { StandardBasicTypes.INTEGER ) ); - registerFunction( - "envelope", new StandardSQLFunction( - "ST_Envelope" - ) - ); + registerFunction( "envelope", new StandardSQLFunction( "ST_Envelope" ) ); registerFunction( "astext", new StandardSQLFunction( "ST_AsText", @@ -146,9 +101,7 @@ public class GeoDBDialect extends H2Dialect implements SpatialDialect { StandardBasicTypes.BOOLEAN ) ); - // NOT YET AVAILABLE IN GEODB - // registerFunction("boundary", new StandardSQLFunction("boundary", - // new CustomType(GeoDBGeometryUserType.class, null))); + registerFunction( "boundary", new StandardSQLFunction( "ST_Boundary" ) ); // Register functions for spatial relation constructs registerFunction( @@ -199,10 +152,12 @@ public class GeoDBDialect extends H2Dialect implements SpatialDialect { StandardBasicTypes.BOOLEAN ) ); - // NOT YET AVAILABLE IN GEODB - // registerFunction("relate", new StandardSQLFunction("relate", - // Hibernate.BOOLEAN)); - + registerFunction( + "relate", new StandardSQLFunction( + "ST_Relate", + StandardBasicTypes.BOOLEAN + ) + ); // register the spatial analysis functions registerFunction( "distance", new StandardSQLFunction( @@ -210,28 +165,12 @@ public class GeoDBDialect extends H2Dialect implements SpatialDialect { StandardBasicTypes.DOUBLE ) ); - registerFunction( - "buffer", new StandardSQLFunction( - "ST_Buffer" - ) - ); - // NOT YET AVAILABLE IN GEODB - // registerFunction("convexhull", new StandardSQLFunction("convexhull", - // new CustomType(GeoDBGeometryUserType.class, null))); - // registerFunction("difference", new StandardSQLFunction("difference", - // new CustomType(GeoDBGeometryUserType.class, null))); - // registerFunction("intersection", new StandardSQLFunction( - // "intersection", new CustomType(GeoDBGeometryUserType.class, null))); - // registerFunction("symdifference", - // new StandardSQLFunction("symdifference", new CustomType( - // GeoDBGeometryUserType.class, null))); - // registerFunction("geomunion", new StandardSQLFunction("geomunion", - // new CustomType(GeoDBGeometryUserType.class, null))); - - //register Spatial Aggregate funciton - // NOT YET AVAILABLE IN GEODB - // registerFunction("extent", new StandardSQLFunction("extent", - // new CustomType(GeoDBGeometryUserType.class, null))); + registerFunction( "buffer", new StandardSQLFunction( "ST_Buffer" ) ); + registerFunction( "convexhull", new StandardSQLFunction( "ST_ConvexHull" ) ); + registerFunction( "difference", new StandardSQLFunction( "ST_Difference" ) ); + registerFunction( "intersection", new StandardSQLFunction( "ST_Intersection" ) ); + registerFunction( "symdifference", new StandardSQLFunction( "ST_SymDifference" ) ); + registerFunction( "geomunion", new StandardSQLFunction( "ST_Union" ) ); registerFunction( "dwithin", new StandardSQLFunction( diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQL56InnoDBSpatialDialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQL56InnoDBSpatialDialect.java new file mode 100644 index 0000000000..bd261100ce --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQL56InnoDBSpatialDialect.java @@ -0,0 +1,47 @@ +/* + * This file is part of Hibernate Spatial, an extension to the + * hibernate ORM solution for spatial (geographic) data. + * + * Copyright © 2007-2013 Geovise BVBA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.hibernate.spatial.dialect.mysql; + +/** + * Spatial Dialect for MySQL 5.6 with InnoDB engine. + * + * @author Karel Maesen, Geovise BVBA + * creation-date: 9/13/13 + */ +public class MySQL56InnoDBSpatialDialect extends MySQL56SpatialDialect { + + @Override + public boolean supportsCascadeDelete() { + return true; + } + + @Override + public String getTableTypeString() { + return " ENGINE=InnoDB"; + } + + @Override + public boolean hasSelfReferentialForeignKeyBug() { + return true; + } + +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQL56SpatialDialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQL56SpatialDialect.java new file mode 100644 index 0000000000..0f181f6eba --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQL56SpatialDialect.java @@ -0,0 +1,132 @@ +package org.hibernate.spatial.dialect.mysql; + +/** + * @author Karel Maesen, Geovise BVBA + * creation-date: 10/9/13 + */ + +import java.util.Map; + +import org.hibernate.HibernateException; +import org.hibernate.dialect.MySQL5Dialect; +import org.hibernate.dialect.function.StandardSQLFunction; +import org.hibernate.spatial.SpatialDialect; +import org.hibernate.spatial.SpatialFunction; +import org.hibernate.spatial.SpatialRelation; +import org.hibernate.type.StandardBasicTypes; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; + +/** + * Extends the MySQL5Dialect by including support for the spatial operators. + * + * This SpatialDialect uses the ST_* spatial operators that operate on exact geometries which have been + * added in MySQL version 5.6.1. Previous versions of MySQL only supported operators that operated on Minimum Bounding + * Rectangles (MBR's). This dialect my therefore produce different results than the other MySQL spatial dialects. + * + * @author Karel Maesen + */ +public class MySQL56SpatialDialect extends MySQL5Dialect implements SpatialDialect { + + + private MySQLSpatialDialect dialectDelegate = new MySQLSpatialDialect(); + + /** + * Constructs the dialect + */ + public MySQL56SpatialDialect() { + super(); + registerColumnType( + MySQLGeometryTypeDescriptor.INSTANCE.getSqlType(), + "GEOMETRY" + ); + final MySQLSpatialFunctions functionsToRegister = overrideObjectShapeFunctions( new MySQLSpatialFunctions() ); + for ( Map.Entry entry : functionsToRegister ) { + registerFunction( entry.getKey(), entry.getValue() ); + } + } + + private MySQLSpatialFunctions overrideObjectShapeFunctions(MySQLSpatialFunctions mysqlFunctions) { + mysqlFunctions.put( "contains", new StandardSQLFunction( "ST_Contains", StandardBasicTypes.BOOLEAN ) ); + mysqlFunctions.put( "crosses", new StandardSQLFunction( "ST_Crosses", StandardBasicTypes.BOOLEAN ) ); + mysqlFunctions.put( "disjoint", new StandardSQLFunction( "ST_Disjoint", StandardBasicTypes.BOOLEAN ) ); + mysqlFunctions.put( "equals", new StandardSQLFunction( "ST_Equals", StandardBasicTypes.BOOLEAN ) ); + mysqlFunctions.put( "intersects", new StandardSQLFunction( "ST_Intersects", StandardBasicTypes.BOOLEAN ) ); + mysqlFunctions.put( "overlaps", new StandardSQLFunction( "ST_Overlaps", StandardBasicTypes.BOOLEAN ) ); + mysqlFunctions.put( "touches", new StandardSQLFunction( "ST_Touches", StandardBasicTypes.BOOLEAN ) ); + mysqlFunctions.put( "within", new StandardSQLFunction( "ST_Within", StandardBasicTypes.BOOLEAN ) ); + return mysqlFunctions; + } + + @Override + public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) { + return dialectDelegate.remapSqlTypeDescriptor( sqlTypeDescriptor ); + } + + @Override + public String getTypeName(int code, long length, int precision, int scale) throws HibernateException { + return dialectDelegate.getTypeName( code, length, precision, scale ); + } + + @Override + public String getSpatialRelateSQL(String columnName, int spatialRelation) { + switch ( spatialRelation ) { + case SpatialRelation.WITHIN: + return " ST_Within(" + columnName + ",?)"; + case SpatialRelation.CONTAINS: + return " ST_Contains(" + columnName + ", ?)"; + case SpatialRelation.CROSSES: + return " ST_Crosses(" + columnName + ", ?)"; + case SpatialRelation.OVERLAPS: + return " ST_Overlaps(" + columnName + ", ?)"; + case SpatialRelation.DISJOINT: + return " ST_Disjoint(" + columnName + ", ?)"; + case SpatialRelation.INTERSECTS: + return " ST_Intersects(" + columnName + ", ?)"; + case SpatialRelation.TOUCHES: + return " ST_Touches(" + columnName + ", ?)"; + case SpatialRelation.EQUALS: + return " ST_Equals(" + columnName + ", ?)"; + default: + throw new IllegalArgumentException( + "Spatial relation is not known by this dialect" + ); + } + } + + @Override + public String getSpatialFilterExpression(String columnName) { + return dialectDelegate.getSpatialFilterExpression( columnName ); + } + + @Override + public String getSpatialAggregateSQL(String columnName, int aggregation) { + return dialectDelegate.getSpatialAggregateSQL( columnName, aggregation ); + } + + @Override + public String getDWithinSQL(String columnName) { + return dialectDelegate.getDWithinSQL( columnName ); + } + + @Override + public String getHavingSridSQL(String columnName) { + return dialectDelegate.getHavingSridSQL( columnName ); + } + + @Override + public String getIsEmptySQL(String columnName, boolean isEmpty) { + return dialectDelegate.getIsEmptySQL( columnName, isEmpty ); + } + + @Override + public boolean supportsFiltering() { + return dialectDelegate.supportsFiltering(); + } + + @Override + public boolean supports(SpatialFunction function) { + return dialectDelegate.supports( function ); + } + +} + diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQL5SpatialInnoDBDialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQL5InnoDBSpatialDialect.java similarity index 96% rename from hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQL5SpatialInnoDBDialect.java rename to hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQL5InnoDBSpatialDialect.java index 85a0d29773..875dc8edde 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQL5SpatialInnoDBDialect.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQL5InnoDBSpatialDialect.java @@ -17,14 +17,14 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; * @author Karel Maesen, Geovise BVBA * */ -public class MySQL5SpatialInnoDBDialect extends MySQL5InnoDBDialect implements SpatialDialect { +public class MySQL5InnoDBSpatialDialect extends MySQL5InnoDBDialect implements SpatialDialect { private MySQLSpatialDialect dialectDelegate = new MySQLSpatialDialect(); /** * Constructs an instance */ - public MySQL5SpatialInnoDBDialect() { + public MySQL5InnoDBSpatialDialect() { super(); registerColumnType( MySQLGeometryTypeDescriptor.INSTANCE.getSqlType(), diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLSpatialFunctions.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLSpatialFunctions.java index 8c619b4451..371c895db8 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLSpatialFunctions.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/mysql/MySQLSpatialFunctions.java @@ -165,6 +165,10 @@ class MySQLSpatialFunctions implements Iterable> iterator() { return functionsToRegister.entrySet().iterator(); diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ConnectionFinder.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ConnectionFinder.java index 717463e181..d94e6ecca8 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ConnectionFinder.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/ConnectionFinder.java @@ -35,6 +35,7 @@ import org.hibernate.spatial.helper.FinderStrategy; * a wrapper. Implementations of this interface attempt to retrieve the * OracleConnection from the wrapper in such cases. *

+ *

Implementations should be thread-safe, and have a default (no-args) constructor.

* * @author Karel Maesen */ diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleJDBCTypeFactory.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleJDBCTypeFactory.java index 97ee2033e6..2ce13c69a0 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleJDBCTypeFactory.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleJDBCTypeFactory.java @@ -44,19 +44,29 @@ import org.hibernate.spatial.helper.FinderException; */ public class OracleJDBCTypeFactory implements SQLTypeFactory { - private static Class datumClass; - private static Class numberClass; - private static Class arrayClass; - private static Class structClass; - private static Class arrayDescriptorClass; - private static Class structDescriptorClass; - private static Method structDescriptorCreator; - private static Method arrayDescriptorCreator; - private static Constructor numberConstructor; - private static Constructor arrayConstructor; - private static Constructor structConstructor; + private final Class datumClass; + private final Class numberClass; + private final Class arrayClass; + private final Class structClass; + private final Class arrayDescriptorClass; + private final Class structDescriptorClass; + private final Method structDescriptorCreator; + private final Method arrayDescriptorCreator; + private final Constructor numberConstructor; + private final Constructor arrayConstructor; + private final Constructor structConstructor; + private final ConnectionFinder connectionFinder; - static { + /** + * Constructs an instance. + * + * @param connectionFinder the {@code ConnectionFinder} the use for retrieving the {@code OracleConnection} instance. + */ + public OracleJDBCTypeFactory(ConnectionFinder connectionFinder) { + if ( connectionFinder == null ) { + throw new HibernateException( "ConnectionFinder cannot be null" ); + } + this.connectionFinder = connectionFinder; Object[] obj = findDescriptorCreator( "oracle.sql.StructDescriptor" ); structDescriptorClass = (Class) obj[0]; structDescriptorCreator = (Method) obj[1]; @@ -73,9 +83,7 @@ public class OracleJDBCTypeFactory implements SQLTypeFactory { structConstructor = findConstructor( structClass, structDescriptorClass, Connection.class, Object[].class ); } - private static ConnectionFinder connectionFinder = new DefaultConnectionFinder(); - - private static Constructor findConstructor(Class clazz, Class... arguments) { + private Constructor findConstructor(Class clazz, Class... arguments) { try { return clazz.getConstructor( arguments ); } @@ -84,7 +92,7 @@ public class OracleJDBCTypeFactory implements SQLTypeFactory { } } - private static Class findClass(String name) { + private Class findClass(String name) { try { return ReflectHelper.classForName( name ); } @@ -93,7 +101,7 @@ public class OracleJDBCTypeFactory implements SQLTypeFactory { } } - private static Object[] findDescriptorCreator(String className) { + private Object[] findDescriptorCreator(String className) { try { final Class clazz = ReflectHelper.classForName( className ); final Method m = clazz.getMethod( "createDescriptor", String.class, Connection.class ); @@ -107,14 +115,6 @@ public class OracleJDBCTypeFactory implements SQLTypeFactory { } } - static ConnectionFinder getConnectionFinder() { - return connectionFinder; - } - - static void setConnectionFinder(ConnectionFinder finder) { - connectionFinder = finder; - } - @Override public Struct createStruct(SDOGeometry geom, Connection conn) throws SQLException { Connection oracleConnection = null; diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleSpatial10gDialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleSpatial10gDialect.java index e34efd0c8f..512341b611 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleSpatial10gDialect.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleSpatial10gDialect.java @@ -20,14 +20,10 @@ */ package org.hibernate.spatial.dialect.oracle; -import java.io.IOException; -import java.io.InputStream; + import java.io.Serializable; -import java.net.URL; -import java.util.HashMap; +import java.sql.Types; import java.util.List; -import java.util.Map; -import java.util.Properties; import org.hibernate.QueryException; import org.hibernate.dialect.Oracle10gDialect; @@ -36,15 +32,13 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.metamodel.spi.TypeContributions; import org.hibernate.service.ServiceRegistry; import org.hibernate.spatial.GeolatteGeometryType; +import org.hibernate.spatial.HibernateSpatialConfiguration; import org.hibernate.spatial.JTSGeometryType; -import org.hibernate.spatial.Log; -import org.hibernate.spatial.LogFactory; import org.hibernate.spatial.SpatialAnalysis; import org.hibernate.spatial.SpatialDialect; import org.hibernate.spatial.SpatialFunction; import org.hibernate.spatial.SpatialRelation; import org.hibernate.spatial.dialect.oracle.criterion.OracleSpatialAggregate; -import org.hibernate.spatial.helper.PropertyFileReader; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.Type; @@ -56,33 +50,31 @@ import org.hibernate.type.Type; public class OracleSpatial10gDialect extends Oracle10gDialect implements SpatialDialect, Serializable { + private final boolean isOgcStrict; + private final ConnectionFinder connectionFinder; + /** - * Short name for this dialect - */ - public static final String SHORT_NAME = "oraclespatial"; - private static final String CONNECTION_FINDER_PROPERTY = "CONNECTION-FINDER"; - private static final Log LOG = LogFactory.make(); - private String ogcStrict = "OGC_STRICT"; - private Map features = new HashMap(); - - /** - * Creates a dialect instance + * Constructs the dialect with a default configuration */ public OracleSpatial10gDialect() { - super(); - // initialise features to default - features.put( ogcStrict, new Boolean( true ) ); + this( new HibernateSpatialConfiguration() ); + } + + /** + * Constructs the dialect with the specified configuration + * + * @param config the {@code HibernateSpatialConfiguration} that configures this dialect. + */ + public OracleSpatial10gDialect(HibernateSpatialConfiguration config) { + super(); + this.isOgcStrict = config.isOgcStrictMode(); + final ConnectionFinder finder = config.getConnectionFinder(); + this.connectionFinder = finder == null ? new DefaultConnectionFinder() : finder; - // read configuration information from - // classpath - configure(); // register geometry type - registerColumnType( - SDOGeometryTypeDescriptor.INSTANCE.getSqlType(), - SDOGeometryTypeDescriptor.INSTANCE.getTypeName() - ); + registerColumnType( Types.STRUCT, "MDSYS.SDO_GEOMETRY" ); // registering OGC functions // (spec_simplefeatures_sql_99-04.pdf) @@ -143,6 +135,7 @@ public class OracleSpatial10gDialect extends Oracle10gDialect implements registerFunction( "extent", new SpatialAggregationFunction( "extent", false, OracleSpatialAggregate.EXTENT ) ); //other common functions + registerFunction( "transform", new StandardSQLFunction( "SDO_CS.TRANSFORM" ) ); // Oracle specific Aggregate functions @@ -174,8 +167,16 @@ public class OracleSpatial10gDialect extends Oracle10gDialect implements typeContributions, serviceRegistry ); - typeContributions.contributeType( new GeolatteGeometryType( SDOGeometryTypeDescriptor.INSTANCE ) ); - typeContributions.contributeType( new JTSGeometryType( SDOGeometryTypeDescriptor.INSTANCE ) ); + + final SDOGeometryTypeDescriptor sdoGeometryTypeDescriptor = new SDOGeometryTypeDescriptor( + new OracleJDBCTypeFactory( + this.connectionFinder + ) + ); + + typeContributions.contributeType( new GeolatteGeometryType( sdoGeometryTypeDescriptor ) ); + typeContributions.contributeType( new JTSGeometryType( sdoGeometryTypeDescriptor ) ); + } String getNativeSpatialRelateSQL(String arg1, String arg2, int spatialRelation) { @@ -214,19 +215,15 @@ public class OracleSpatial10gDialect extends Oracle10gDialect implements + ")" ); } - StringBuffer buffer; - if ( negate ) { - buffer = new StringBuffer( "CASE WHEN SDO_RELATE(" ); + final StringBuffer buffer = new StringBuffer( "CASE SDO_RELATE(" ).append( arg1 ) + .append( "," ) + .append( arg2 ) + .append( ",'mask=" + mask + "') " ); + if ( !negate ) { + buffer.append( " WHEN 'TRUE' THEN 1 ELSE 0 END" ); } else { - buffer = new StringBuffer( "SDO_RELATE(" ); - } - - - buffer.append( arg1 ); - buffer.append( "," ).append( arg2 ).append( ",'mask=" + mask + "') " ); - if ( negate ) { - buffer.append( " = 'TRUE' THEN 'FALSE' ELSE 'TRUE' END" ); + buffer.append( " WHEN 'TRUE' THEN 0 ELSE 1 END" ); } return buffer.toString(); } @@ -308,9 +305,6 @@ public class OracleSpatial10gDialect extends Oracle10gDialect implements @Override public String getSpatialFilterExpression(String columnName) { final StringBuffer buffer = new StringBuffer( "SDO_FILTER(" ); - // String pureColumnName = - // columnName.substring(columnName.lastIndexOf(".")+1); - // buffer.append("\"" + pureColumnName.toUpperCase() + "\""); buffer.append( columnName ); buffer.append( ",?) = 'TRUE' " ); return buffer.toString(); @@ -318,12 +312,9 @@ public class OracleSpatial10gDialect extends Oracle10gDialect implements @Override public String getSpatialRelateSQL(String columnName, int spatialRelation) { - String sql = ( isOGCStrict() ? ( getOGCSpatialRelateSQL( - columnName, "?", - spatialRelation - ) + " = 1" ) : ( getNativeSpatialRelateSQL( - columnName, "?", spatialRelation - ) + "= 'TRUE'" ) ); + String sql = ( isOGCStrict() ? + getOGCSpatialRelateSQL( columnName, "?", spatialRelation ) : + getNativeSpatialRelateSQL( columnName, "?", spatialRelation ) ) + " = 1"; sql += " and " + columnName + " is not null"; return sql; } @@ -342,7 +333,7 @@ public class OracleSpatial10gDialect extends Oracle10gDialect implements @Override public String getDWithinSQL(String columnName) { - throw new UnsupportedOperationException( "No DWithin in this dialect" ); + return "SDO_WITHIN_DISTANCE (" + columnName + ",?, ?) = 'TRUE' "; } @Override @@ -426,55 +417,26 @@ public class OracleSpatial10gDialect extends Oracle10gDialect implements return getOGCSpatialAnalysisSQL( args, spatialAnalysis ); } - boolean isOGCStrict() { - return this.features.get( ogcStrict ); + /** + * Reports whether this dialect is in OGC_STRICT mode or not. + * + * This method is for testing purposes. + * + * @return true if in OGC_STRICT mode, false otherwise + */ + public boolean isOGCStrict() { + return isOgcStrict; } - private void configure() { - final ClassLoader loader = Thread.currentThread().getContextClassLoader(); - final String propfileLoc = getClass().getCanonicalName() + ".properties"; - final URL propfile = loader.getResource( propfileLoc ); - if ( propfile != null ) { - InputStream is = null; - LOG.info( "properties file found: " + propfile ); - try { - loader.getResource( getClass().getCanonicalName() ); - is = propfile.openStream(); - final PropertyFileReader reader = new PropertyFileReader( is ); - final Properties props = reader.getProperties(); - - // checking for connectionfinder - final String ccn = props.getProperty( CONNECTION_FINDER_PROPERTY ); - if ( ccn != null ) { - try { - final Class clazz = Thread.currentThread().getContextClassLoader().loadClass( ccn ); - final ConnectionFinder cf = (ConnectionFinder) clazz.newInstance(); - OracleJDBCTypeFactory.setConnectionFinder( cf ); - LOG.info( "Setting ConnectionFinder to " + ccn ); - } - catch ( ClassNotFoundException e ) { - LOG.warn( "Tried to set ConnectionFinder to " + ccn + ", but class not found." ); - } - catch ( InstantiationException e ) { - LOG.warn( "Tried to set ConnectionFinder to " + ccn + ", but couldn't instantiate." ); - } - catch ( IllegalAccessException e ) { - LOG.warn( "Tried to set ConnectionFinder to " + ccn + ", but got IllegalAcessException on instantiation." ); - } - } - - } - catch ( IOException e ) { - LOG.warn( "Problem reading properties file " + e ); - } - finally { - try { - is.close(); - } - catch ( Exception e ) { - } - } - } + /** + * Reports the ConnectionFinder used by this Dialect (or rather its associated TypeDescriptor). + * + * This method is mainly used for testing purposes. + * + * @return the ConnectionFinder in use + */ + public ConnectionFinder getConnectionFinder() { + return connectionFinder; } @Override @@ -490,7 +452,7 @@ public class OracleSpatial10gDialect extends Oracle10gDialect implements /** * Implementation of the OGC astext function for HQL. */ - private class AsTextFunction extends StandardSQLFunction { + private static class AsTextFunction extends StandardSQLFunction { private AsTextFunction() { super( "astext", StandardBasicTypes.STRING ); diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometry.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometry.java index a4c6eea576..37fa43c27d 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometry.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometry.java @@ -22,14 +22,11 @@ package org.hibernate.spatial.dialect.oracle; import java.sql.Array; -import java.sql.Connection; import java.sql.SQLException; import java.sql.Struct; import java.util.ArrayList; import java.util.List; -import org.hibernate.spatial.helper.FinderException; - /** * @author Karel Maesen, Geovise BVBA * creation-date: Jun 30, 2010 @@ -37,7 +34,6 @@ import org.hibernate.spatial.helper.FinderException; class SDOGeometry { - private static final SQLTypeFactory TYPE_FACTORY = new OracleJDBCTypeFactory(); private static final String SQL_TYPE_NAME = "MDSYS.SDO_GEOMETRY"; private SDOGType gtype; private int srid; @@ -102,33 +98,6 @@ class SDOGeometry { return sdoCollection; } - public static SDOGeometry load(Struct struct) { - - Object[] data; - try { - data = struct.getAttributes(); - } - catch ( SQLException e ) { - throw new RuntimeException( e ); - } - - final SDOGeometry geom = new SDOGeometry(); - geom.setGType( SDOGType.parse( data[0] ) ); - geom.setSRID( data[1] ); - if ( data[2] != null ) { - geom.setPoint( new SDOPoint( (Struct) data[2] ) ); - } - geom.setInfo( new ElemInfo( (Array) data[3] ) ); - geom.setOrdinates( new Ordinates( (Array) data[4] ) ); - - return geom; - } - - public static Struct store(SDOGeometry geom, Connection conn) - throws SQLException, FinderException { - return TYPE_FACTORY.createStruct( geom, conn ); - } - private static void shiftOrdinateOffset(ElemInfo elemInfo, int offset) { for ( int i = 0; i < elemInfo.getSize(); i++ ) { final int newOffset = elemInfo.getOrdinatesOffset( i ) + offset; @@ -171,6 +140,28 @@ class SDOGeometry { } } + public static SDOGeometry load(Struct struct) { + + Object[] data; + try { + data = struct.getAttributes(); + } + catch ( SQLException e ) { + throw new RuntimeException( e ); + } + + final SDOGeometry geom = new SDOGeometry(); + geom.setGType( SDOGType.parse( data[0] ) ); + geom.setSRID( data[1] ); + if ( data[2] != null ) { + geom.setPoint( new SDOPoint( (Struct) data[2] ) ); + } + geom.setInfo( new ElemInfo( (Array) data[3] ) ); + geom.setOrdinates( new Ordinates( (Array) data[4] ) ); + + return geom; + } + public ElemInfo getInfo() { return info; } @@ -207,23 +198,23 @@ class SDOGeometry { return srid; } + public void setSRID(int srid) { + this.srid = srid; + } + private void setSRID(Object datum) { if ( datum == null ) { this.srid = 0; return; } try { - this.srid = new Integer( ( (Number) datum ).intValue() ); + this.srid = ( (Number) datum ).intValue(); } catch ( Exception e ) { throw new RuntimeException( e ); } } - public void setSRID(int srid) { - this.srid = srid; - } - public boolean isLRSGeometry() { return gtype.isLRSGeometry(); } diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryTypeDescriptor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryTypeDescriptor.java index b209b9e52d..a1fdfe8133 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryTypeDescriptor.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryTypeDescriptor.java @@ -36,10 +36,16 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; */ public class SDOGeometryTypeDescriptor implements SqlTypeDescriptor { + private final OracleJDBCTypeFactory typeFactory; + /** - * An instance of this class + * Constructs a {@code SqlTypeDescriptor} for the Oracle SDOGeometry type. + * + * @param typeFactory the type factory to use. */ - public static final SDOGeometryTypeDescriptor INSTANCE = new SDOGeometryTypeDescriptor(); + public SDOGeometryTypeDescriptor(OracleJDBCTypeFactory typeFactory) { + this.typeFactory = typeFactory; + } @Override public int getSqlType() { @@ -53,14 +59,18 @@ public class SDOGeometryTypeDescriptor implements SqlTypeDescriptor { @Override public ValueBinder getBinder(final JavaTypeDescriptor javaTypeDescriptor) { - return new SDOGeometryValueBinder( javaTypeDescriptor ); + return (ValueBinder) new SDOGeometryValueBinder( javaTypeDescriptor, this, typeFactory ); } @Override public ValueExtractor getExtractor(final JavaTypeDescriptor javaTypeDescriptor) { - return (ValueExtractor) new SDOGeometryValueExtractor( javaTypeDescriptor ); + return (ValueExtractor) new SDOGeometryValueExtractor( javaTypeDescriptor, this ); } + /** + * Returns the Oracle type name for SDOGeometry. + * @return the Oracle type name + */ public String getTypeName() { return "MDSYS.SDO_GEOMETRY"; } diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueBinder.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueBinder.java index 0dec83b5d7..361fa0ddf3 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueBinder.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueBinder.java @@ -24,6 +24,7 @@ package org.hibernate.spatial.dialect.oracle; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.Types; import com.vividsolutions.jts.algorithm.CGAlgorithms; import com.vividsolutions.jts.geom.Coordinate; @@ -37,13 +38,11 @@ import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; import org.hibernate.HibernateException; -import org.hibernate.spatial.Log; -import org.hibernate.spatial.LogFactory; import org.hibernate.spatial.helper.FinderException; -import org.hibernate.type.descriptor.JdbcTypeNameMapper; import org.hibernate.type.descriptor.ValueBinder; import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; /** * @author Karel Maesen, Geovise BVBA @@ -51,55 +50,36 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor; */ class SDOGeometryValueBinder implements ValueBinder { - private static final Log LOG = LogFactory.make(); - private static final String BIND_MSG_TEMPLATE = "binding parameter [%s] as [%s] - %s"; - private static final String NULL_BIND_MSG_TEMPLATE = "binding parameter [%s] as [%s] - "; - private final JavaTypeDescriptor javaDescriptor; + private final OracleJDBCTypeFactory typeFactory; + private final JavaTypeDescriptor javaTypeDescriptor; - public SDOGeometryValueBinder(JavaTypeDescriptor javaDescriptor) { - this.javaDescriptor = javaDescriptor; + public SDOGeometryValueBinder(JavaTypeDescriptor javaTypeDescriptor, SqlTypeDescriptor sqlTypeDescriptor, OracleJDBCTypeFactory typeFactory) { + this.javaTypeDescriptor = javaTypeDescriptor; + this.typeFactory = typeFactory; } - public final void bind(PreparedStatement st, J value, int index, WrapperOptions options) throws SQLException { + @Override + public void bind(PreparedStatement st, J value, int index, WrapperOptions options) throws SQLException { if ( value == null ) { - if ( LOG.isTraceEnabled() ) { - LOG.trace( - String.format( - NULL_BIND_MSG_TEMPLATE, - index, - JdbcTypeNameMapper.getTypeName( SDOGeometryTypeDescriptor.INSTANCE.getSqlType() ) - ) - ); - } - st.setNull( - index, - SDOGeometryTypeDescriptor.INSTANCE.getSqlType(), - SDOGeometryTypeDescriptor.INSTANCE.getTypeName() - ); + st.setNull( index, Types.STRUCT, SDOGeometry.getTypeName() ); } else { - if ( LOG.isTraceEnabled() ) { - LOG.trace( - String.format( - BIND_MSG_TEMPLATE, - index, - JdbcTypeNameMapper.getTypeName( SDOGeometryTypeDescriptor.INSTANCE.getSqlType() ), - javaDescriptor.extractLoggableRepresentation( value ) - ) - ); - } - final Geometry jtsGeom = javaDescriptor.unwrap( value, Geometry.class, options ); + final Geometry jtsGeom = javaTypeDescriptor.unwrap( value, Geometry.class, options ); final Object dbGeom = toNative( jtsGeom, st.getConnection() ); st.setObject( index, dbGeom ); } } - protected Object toNative(Geometry jtsGeom, Connection connection) { + public Object store(SDOGeometry geom, Connection conn) throws SQLException, FinderException { + return typeFactory.createStruct( geom, conn ); + } + + private Object toNative(Geometry jtsGeom, Connection connection) { final SDOGeometry geom = convertJTSGeometry( jtsGeom ); if ( geom != null ) { try { - return SDOGeometry.store( geom, connection ); + return store( geom, connection ); } catch ( SQLException e ) { throw new HibernateException( diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueExtractor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueExtractor.java index 687f567a25..124955d13a 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueExtractor.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/SDOGeometryValueExtractor.java @@ -44,6 +44,7 @@ import org.hibernate.spatial.jts.Circle; import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.sql.BasicExtractor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; //TODO -- requires cleanup and must be made package local @@ -62,10 +63,11 @@ public class SDOGeometryValueExtractor extends BasicExtractor { /** * Creates instance * - * @param javaDescriptor javadescriptor to use + * @param javaDescriptor the {@code JavaTypeDescriptor} to use + * @param sqlTypeDescriptor the {@code SqlTypeDescriptor} to use */ - public SDOGeometryValueExtractor(JavaTypeDescriptor javaDescriptor) { - super( javaDescriptor, SDOGeometryTypeDescriptor.INSTANCE ); + public SDOGeometryValueExtractor(JavaTypeDescriptor javaDescriptor, SqlTypeDescriptor sqlTypeDescriptor ) { + super( javaDescriptor, sqlTypeDescriptor ); } @Override diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/helper/FinderStrategy.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/helper/FinderStrategy.java index 0588f6d987..9b70d75241 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/helper/FinderStrategy.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/helper/FinderStrategy.java @@ -20,6 +20,8 @@ */ package org.hibernate.spatial.helper; +import java.io.Serializable; + /** * A FinderStrategy is used to find a specific feature. It is * useful in cases where reflection is used to determine some property of a @@ -30,7 +32,7 @@ package org.hibernate.spatial.helper; * * @author Karel Maesen */ -public interface FinderStrategy { +public interface FinderStrategy extends Serializable { /** * Find a feature or property of a subject diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/SpatialDialectFactory.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/SpatialDialectFactory.java new file mode 100644 index 0000000000..cb4674520b --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/SpatialDialectFactory.java @@ -0,0 +1,44 @@ +package org.hibernate.spatial.integration; + +import java.sql.Connection; +import java.util.Map; + +import org.hibernate.HibernateException; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl; +import org.hibernate.spatial.HibernateSpatialConfiguration; +import org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect; + +/** + * A {@code DialectFactory} that may inject configuration into {@code SpatialDialect}s. + * + * This implementation extends the Standard Hibernate {@code DialectFactory}. It is currently only used for the + * {@code OracleSpatial10gDialect}. + * + * @author Karel Maesen, Geovise BVBA + * creation-date: 8/23/13 + */ +public class SpatialDialectFactory extends DialectFactoryImpl { + + private final HibernateSpatialConfiguration configuration; + + /** + * Constructs an instance with the specified configuration + * @param configuration the {@HibernateSpatialConfiguration} to use. + */ + public SpatialDialectFactory(HibernateSpatialConfiguration configuration) { + super(); + this.configuration = configuration; + } + + @Override + public Dialect buildDialect(Map configValues, Connection connection) throws HibernateException { + final Dialect dialect = super.buildDialect( configValues, connection ); + if (dialect instanceof OracleSpatial10gDialect) { + return new OracleSpatial10gDialect( configuration ); + } + else { + return dialect; + } + } +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/SpatialInitiator.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/SpatialInitiator.java new file mode 100644 index 0000000000..356d22bc12 --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/SpatialInitiator.java @@ -0,0 +1,89 @@ +package org.hibernate.spatial.integration; + +import java.util.Map; + +import org.hibernate.HibernateException; +import org.hibernate.boot.registry.StandardServiceInitiator; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.jdbc.dialect.spi.DialectFactory; +import org.hibernate.service.Service; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.spatial.HibernateSpatialConfiguration; +import org.hibernate.spatial.dialect.oracle.ConnectionFinder; + +/** + * The {@code ServiceInitiator} for Hibernate Spatial. + * + * @author Karel Maesen, Geovise BVBA + * creation-date: 8/23/13 + */ +public class SpatialInitiator implements StandardServiceInitiator { + + @Override + public Class getServiceInitiated() { + return DialectFactory.class; + } + + @Override + public Service initiateService(Map configurationValues, ServiceRegistryImplementor registry) { + final HibernateSpatialConfiguration configuration = configure( registry ); + return new SpatialDialectFactory( configuration ); + } + + private HibernateSpatialConfiguration configure(ServiceRegistry serviceRegistry) { + final ConfigurationService configService = serviceRegistry.getService( ConfigurationService.class ); + final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + return new HibernateSpatialConfiguration( + readOgcStrict( configService ), + readConnectionFinder( configService, classLoaderService ) + ); + } + + /** + * Reads the configured property (if present), otherwise returns null + */ + private Boolean readOgcStrict(ConfigurationService configService) { + final String ogcStrictKey = HibernateSpatialConfiguration.AvailableSettings.OGC_STRICT; + return configService.getSetting( + ogcStrictKey, + new ConfigurationService.Converter() { + @Override + public Boolean convert(Object value) { + return Boolean.parseBoolean( value.toString() ); + } + }, null + ); + } + + /** + * Reads the configured property (if present), otherwise returns null + */ + private ConnectionFinder readConnectionFinder(ConfigurationService configService, ClassLoaderService classLoaderService) { + final String cfKey = HibernateSpatialConfiguration.AvailableSettings.CONNECTION_FINDER; + final String className = configService.getSetting( + cfKey, + new ConfigurationService.Converter() { + @Override + public String convert(Object value) { + if ( value instanceof String ) { + return (String) value; + } + return value.toString(); + } + }, null + ); + + if ( className == null ) { + return null; + } + + try { + return (ConnectionFinder) classLoaderService.classForName( className ).newInstance(); + } + catch ( Exception e ) { + throw new HibernateException( " Could not instantiate ConnectionFinder: " + className, e ); + } + } +} diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/package.html b/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/package.html new file mode 100644 index 0000000000..d42f2b2b27 --- /dev/null +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/integration/package.html @@ -0,0 +1,30 @@ + + + + + + +

+ This package contains the integration classes to hook into Hibernate-ORM. +

+ + diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/MockConnectionFinder.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/MockConnectionFinder.java new file mode 100644 index 0000000000..06a8161645 --- /dev/null +++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/MockConnectionFinder.java @@ -0,0 +1,12 @@ +package org.hibernate.spatial.dialect.oracle; + +import java.sql.Connection; + +import org.hibernate.spatial.helper.FinderException; + +public class MockConnectionFinder implements ConnectionFinder { + @Override + public Connection find(Connection subject) throws FinderException { + return null; + } +} diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/OracleSpatial10gConfigurationTest.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/OracleSpatial10gConfigurationTest.java new file mode 100644 index 0000000000..8654f4633d --- /dev/null +++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/dialect/oracle/OracleSpatial10gConfigurationTest.java @@ -0,0 +1,77 @@ +package org.hibernate.spatial.dialect.oracle; + +import org.junit.Assert; +import org.junit.Test; + +import org.hibernate.HibernateException; +import org.hibernate.SessionFactory; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; +import org.hibernate.dialect.Dialect; +import org.hibernate.internal.SessionFactoryImpl; +import org.hibernate.spatial.HibernateSpatialConfiguration; +import org.hibernate.testing.RequiresDialect; +import org.hibernate.testing.ServiceRegistryBuilder; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; + +@RequiresDialect(OracleSpatial10gDialect.class) +public class OracleSpatial10gConfigurationTest extends BaseCoreFunctionalTestCase{ + + + private Configuration addToConfiguration(Configuration cfg, Boolean ogcStrict, String connFinderClassName) { + cfg.setProperty( HibernateSpatialConfiguration.AvailableSettings.CONNECTION_FINDER, connFinderClassName ); + cfg.setProperty( HibernateSpatialConfiguration.AvailableSettings.OGC_STRICT, ogcStrict.toString() ); + return cfg; + } + + private void createdOracleSpatialDialect(Boolean ogcStrict, String connFinderClassName) { + createdOracleSpatialDialect( ogcStrict, connFinderClassName, true ); + } + + private void createdOracleSpatialDialect(Boolean ogcStrict, String connFinderClassName, boolean doConfiguration) { + Configuration cfg = new Configuration(); + if (doConfiguration){ + addToConfiguration( cfg, ogcStrict, connFinderClassName ); + } + cfg.setProperty( AvailableSettings.DIALECT, OracleSpatial10gDialect.class.getCanonicalName() ); + StandardServiceRegistry serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( cfg.getProperties() ); + SessionFactory sessionFactory = cfg.buildSessionFactory( serviceRegistry ); + Dialect d = ( (SessionFactoryImpl) sessionFactory ).getDialect(); + OracleSpatial10gDialect osd = (OracleSpatial10gDialect) d; + Assert.assertTrue( ogcStrict == osd.isOGCStrict() ); + ConnectionFinder finder = osd.getConnectionFinder(); + Assert.assertNotNull( finder ); + Assert.assertEquals( connFinderClassName, finder.getClass().getCanonicalName() ); + } + + @Test + public void testOgcStrictMockFinder() { + createdOracleSpatialDialect( true, MockConnectionFinder.class.getCanonicalName() ); + } + + @Test + public void testOgcNonStrictMockFinder() { + createdOracleSpatialDialect( false, MockConnectionFinder.class.getCanonicalName() ); + } + + @Test + public void testOgcStrictDefaultFinder() { + createdOracleSpatialDialect( true, DefaultConnectionFinder.class.getCanonicalName() ); + } + + @Test + public void testOgcNonStrictDefaultFinder() { + createdOracleSpatialDialect( false, DefaultConnectionFinder.class.getCanonicalName() ); + } + + @Test(expected = HibernateException.class) + public void testOgcStrictNonExistentClass() { + createdOracleSpatialDialect( false, "doesntexist" ); + } + + @Test + public void testNoConfiguration(){ + createdOracleSpatialDialect( true, DefaultConnectionFinder.class.getCanonicalName(), false ); + } +} diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/integration/TestSpatialFunctions.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/integration/TestSpatialFunctions.java index f1febfc306..6f9332426e 100644 --- a/hibernate-spatial/src/test/java/org/hibernate/spatial/integration/TestSpatialFunctions.java +++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/integration/TestSpatialFunctions.java @@ -34,9 +34,12 @@ import org.hibernate.Transaction; import org.hibernate.spatial.Log; import org.hibernate.spatial.LogFactory; import org.hibernate.spatial.SpatialFunction; +import org.hibernate.spatial.dialect.h2geodb.GeoDBDialect; +import org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect; import org.hibernate.spatial.testing.SpatialDialectMatcher; import org.hibernate.spatial.testing.SpatialFunctionalTestCase; import org.hibernate.testing.Skip; +import org.hibernate.testing.SkipForDialect; import static java.lang.String.format; @@ -494,16 +497,18 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase { } - @Test + @Test @SkipForDialect( value = GeoDBDialect.class) public void test_intersection_on_jts()throws SQLException { intersection( JTS ); } - @Test + @Test @SkipForDialect( value = GeoDBDialect.class) public void test_intersection_on_geolatte()throws SQLException { intersection( GEOLATTE); } + //skipped for GeoDBDialect because GeoDB throws exceptions in case the intersection is empty. + // (Error message is "Empty Points cannot be represented in WKB") public void intersection(String pckg) throws SQLException { if ( !isSupportedByDialect( SpatialFunction.intersection ) ) { return; @@ -601,7 +606,15 @@ public class TestSpatialFunctions extends SpatialFunctionalTestCase { "org.hibernate.spatial.integration.%s.GeomEntity where dwithin(geom, :filter, :distance) = true " + "and srid(geom) = 4326", pckg); Map params = createQueryParams( "filter", expectationsFactory.getTestPoint() ); - params.put( "distance", 30.0 ); + if ( getDialect() instanceof OracleSpatial10gDialect ) { + //because this uses the weird syntax and conventions of SDO_WITHIN_DISTANCE which returns a string (really) + // we use a different boolean expression guaranteed to be true, and we set the third parameter to key/value string + hql = "SELECT id, issimple(geom) from org.hibernate.spatial.integration.GeomEntity where dwithin(geom, :filter, :distance) = true and srid(geom) = 4326"; + params.put( "distance", "distance = 30" ); + } + else { + params.put( "distance", 30.0 ); + } retrieveHQLResultsAndCompare( dbexpected, hql, params, pckg ); } diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/SpatialFunctionalTestCase.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/SpatialFunctionalTestCase.java index 678cd2b4b2..cca4136dc5 100644 --- a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/SpatialFunctionalTestCase.java +++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/SpatialFunctionalTestCase.java @@ -49,7 +49,6 @@ import static org.junit.Assert.fail; */ public abstract class SpatialFunctionalTestCase extends BaseCoreFunctionalTestCase { - protected static String JTS = "jts"; protected static String GEOLATTE = "geolatte"; diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/TestSupportFactories.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/TestSupportFactories.java index e031afb2fd..76e506d314 100644 --- a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/TestSupportFactories.java +++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/TestSupportFactories.java @@ -23,6 +23,7 @@ package org.hibernate.spatial.testing; import org.hibernate.dialect.Dialect; import org.hibernate.spatial.testing.dialects.h2geodb.GeoDBTestSupport; +import org.hibernate.spatial.testing.dialects.mysql.MySQL56TestSupport; import org.hibernate.spatial.testing.dialects.mysql.MySQLTestSupport; import org.hibernate.spatial.testing.dialects.oracle.OracleSDOTestSupport; import org.hibernate.spatial.testing.dialects.postgis.PostgisTestSupport; @@ -44,7 +45,6 @@ public class TestSupportFactories { private TestSupportFactories() { } - public TestSupport getTestSupportFactory(Dialect dialect) throws InstantiationException, IllegalAccessException { if ( dialect == null ) { throw new IllegalArgumentException( "Dialect argument is required." ); @@ -63,9 +63,6 @@ public class TestSupportFactories { return this.getClass().getClassLoader(); } - //TODO -- find a better way to initialize and inject the TestSupport class. - //This whole class can probably be made obsolete. - private static Class getSupportFactoryClass(Dialect dialect) { String canonicalName = dialect.getClass().getCanonicalName(); if ( "org.hibernate.spatial.dialect.postgis.PostgisDialect".equals( canonicalName ) ) { @@ -78,10 +75,13 @@ public class TestSupportFactories { return SQLServerTestSupport.class; } if ( "org.hibernate.spatial.dialect.mysql.MySQLSpatialDialect".equals( canonicalName ) || - "org.hibernate.spatial.dialect.mysql.MySQLSpatialInnoDBDialect".equals( canonicalName ) || - "org.hibernate.spatial.dialect.mysql.MySQL5SpatialInnoDBDialect".equals( canonicalName ) ) { + "org.hibernate.spatial.dialect.mysql.MySQL5InnoDBSpatialDialect".equals( canonicalName ) ) { return MySQLTestSupport.class; } + if ( "org.hibernate.spatial.dialect.mysql.MySQLSpatial56Dialect".equals( canonicalName ) || + "org.hibernate.spatial.dialect.mysql.MySQL56InnoDBSpatialDialect".equals( canonicalName ) ) { + return MySQL56TestSupport.class; + } if ( "org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect".equals( canonicalName ) ) { return OracleSDOTestSupport.class; } diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBExpectationsFactory.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBExpectationsFactory.java index f2500485be..180e44f9fb 100644 --- a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBExpectationsFactory.java +++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBExpectationsFactory.java @@ -57,9 +57,7 @@ public class GeoDBExpectationsFactory extends AbstractExpectationsFactory { @Override protected NativeSQLStatement createNativeBoundaryStatement() { - throw new UnsupportedOperationException( - "Method ST_Bounday() is not implemented in the current version of GeoDB." - ); + return createNativeSQLStatement("select id, ST_Boundary(geom) from GEOMTEST"); } @Override @@ -80,8 +78,9 @@ public class GeoDBExpectationsFactory extends AbstractExpectationsFactory { @Override protected NativeSQLStatement createNativeConvexHullStatement(Geometry geom) { - throw new UnsupportedOperationException( - "Method ST_ConvexHull() is not implemented in the current version of GeoDB." + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_ConvexHull(ST_Union(t.geom, ST_GeomFromText(?, 4326))) from GeomTest t where ST_SRID(t.geom) = 4326", + geom.toText() ); } @@ -102,9 +101,7 @@ public class GeoDBExpectationsFactory extends AbstractExpectationsFactory { @Override protected NativeSQLStatement createNativeDimensionSQL() { - throw new UnsupportedOperationException( - "Method ST_Dimension() is not implemented in the current version of GeoDB." - ); + return createNativeSQLStatement("select id, ST_Dimension(geom) from GEOMTEST"); } @Override @@ -193,8 +190,9 @@ public class GeoDBExpectationsFactory extends AbstractExpectationsFactory { @Override protected NativeSQLStatement createNativeGeomUnionStatement(Geometry geom) { - throw new UnsupportedOperationException( - "Method ST_GeomUnion() is not implemented in the current version of GeoDB." + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Union(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_SRID(t.geom) = 4326", + geom.toText() ); } @@ -219,8 +217,9 @@ public class GeoDBExpectationsFactory extends AbstractExpectationsFactory { @Override protected NativeSQLStatement createNativeIntersectionStatement(Geometry geom) { - throw new UnsupportedOperationException( - "Method ST_Intersection() is not implemented in the current version of GeoDB." + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Intersection(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_SRID(t.geom) = 4326", + geom.toText() ); } @@ -294,9 +293,8 @@ public class GeoDBExpectationsFactory extends AbstractExpectationsFactory { @Override protected NativeSQLStatement createNativeRelateStatement(Geometry geom, String matrix) { - throw new UnsupportedOperationException( - "Method ST_Relate() is not implemented in the current version of GeoDB." - ); + String sql = "select t.id, ST_Relate(t.geom, ST_GeomFromText(?, 4326), '" + matrix + "' ) from GEOMTEST t where ST_Relate(t.geom, ST_GeomFromText(?, 4326), '" + matrix + "') = 'true' and ST_SRID(t.geom) = 4326"; + return createNativeSQLStatementAllWKTParams(sql, geom.toText()); } @Override @@ -331,8 +329,9 @@ public class GeoDBExpectationsFactory extends AbstractExpectationsFactory { @Override protected NativeSQLStatement createNativeSymDifferenceStatement( Geometry geom) { - throw new UnsupportedOperationException( - "Method ST_SymDifference() is not implemented in the current version of GeoDB." + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_SymDifference(t.geom, ST_GeomFromText(?, 4326)) from GEOMTEST t where ST_SRID(t.geom) = 4326", + geom.toText() ); } diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBNoSRIDExpectationsFactory.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBNoSRIDExpectationsFactory.java index e849a8d44f..66f07b86d5 100644 --- a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBNoSRIDExpectationsFactory.java +++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/h2geodb/GeoDBNoSRIDExpectationsFactory.java @@ -40,6 +40,7 @@ import org.hibernate.spatial.testing.NativeSQLStatement; * * @author Jan Boonen, Geodan IT b.v. */ +@Deprecated //Class no longer used. Remove. public class GeoDBNoSRIDExpectationsFactory extends AbstractExpectationsFactory { public GeoDBNoSRIDExpectationsFactory(GeoDBDataSourceUtils dataSourceUtils) { diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/mysql/MySQL56ExpectationsFactory.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/mysql/MySQL56ExpectationsFactory.java new file mode 100644 index 0000000000..8bbd8b13b9 --- /dev/null +++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/mysql/MySQL56ExpectationsFactory.java @@ -0,0 +1,75 @@ +package org.hibernate.spatial.testing.dialects.mysql; + +import com.vividsolutions.jts.geom.Geometry; + +import org.hibernate.spatial.testing.DataSourceUtils; +import org.hibernate.spatial.testing.NativeSQLStatement; + +/** + * @author Karel Maesen, Geovise BVBA + * creation-date: 10/9/13 + */ +public class MySQL56ExpectationsFactory extends MySQLExpectationsFactory { + + + public MySQL56ExpectationsFactory(DataSourceUtils dataSourceUtils) { + super( dataSourceUtils ); + } + + @Override + protected NativeSQLStatement createNativeTouchesStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Touches(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where ST_Touches(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeOverlapsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_overlaps(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where ST_Overlaps(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeIntersectsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Intersects(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where ST_Intersects(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeWithinStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Within(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where ST_Within(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeEqualsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Equals(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where ST_Equals(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeCrossesStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Crosses(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where ST_Crosses(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeContainsStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Contains(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where ST_Contains(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + + @Override + protected NativeSQLStatement createNativeDisjointStatement(Geometry geom) { + return createNativeSQLStatementAllWKTParams( + "select t.id, ST_Disjoint(t.geom, GeomFromText(?, 4326)) from GEOMTEST t where ST_Disjoint(t.geom, geomFromText(?, 4326)) = 1 and srid(t.geom) = 4326", + geom.toText()); + } + +} diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/mysql/MySQL56TestSupport.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/mysql/MySQL56TestSupport.java new file mode 100644 index 0000000000..0d5a0531a6 --- /dev/null +++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/mysql/MySQL56TestSupport.java @@ -0,0 +1,16 @@ +package org.hibernate.spatial.testing.dialects.mysql; + +import org.hibernate.spatial.testing.AbstractExpectationsFactory; +import org.hibernate.spatial.testing.DataSourceUtils; + +/** + * @author Karel Maesen, Geovise BVBA + * creation-date: 10/9/13 + */ +public class MySQL56TestSupport extends MySQLTestSupport { + + @Override + public AbstractExpectationsFactory createExpectationsFactory(DataSourceUtils dataSourceUtils) { + return new MySQL56ExpectationsFactory( dataSourceUtils ); + } +} diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/oracle/SDOGeometryExpectationsFactory.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/oracle/SDOGeometryExpectationsFactory.java index 2eae57826d..3e99ed751d 100644 --- a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/oracle/SDOGeometryExpectationsFactory.java +++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/dialects/oracle/SDOGeometryExpectationsFactory.java @@ -37,7 +37,7 @@ import org.hibernate.spatial.testing.NativeSQLStatement; */ public class SDOGeometryExpectationsFactory extends AbstractExpectationsFactory { - private final SDOGeometryValueExtractor decoder = new SDOGeometryValueExtractor( JTSGeometryJavaTypeDescriptor.INSTANCE ); + private final SDOGeometryValueExtractor decoder = new SDOGeometryValueExtractor( JTSGeometryJavaTypeDescriptor.INSTANCE, null ); public SDOGeometryExpectationsFactory(DataSourceUtils dataSourceUtils) { super( dataSourceUtils ); @@ -69,7 +69,10 @@ public class SDOGeometryExpectationsFactory extends AbstractExpectationsFactory @Override protected NativeSQLStatement createNativeDwithinStatement(Point geom, double distance) { - throw new UnsupportedOperationException(); + return createNativeSQLStatementAllWKTParams( + "select t.id, 1 from GEOMTEST T where MDSYS.SDO_WITHIN_DISTANCE(t.GEOM, SDO_GEOMETRY(? , 4326), 'distance = " + distance + "') = 'TRUE' and t.GEOM.SDO_SRID = 4326", + geom.toText() + ); } @Override diff --git a/hibernate-spatial/src/test/resources/hibernate.properties b/hibernate-spatial/src/test/resources/hibernate.properties index 0ef89ea6d7..e0992e3da9 100644 --- a/hibernate-spatial/src/test/resources/hibernate.properties +++ b/hibernate-spatial/src/test/resources/hibernate.properties @@ -50,13 +50,17 @@ hibernate.connection.username sa #hibernate.connection.username hibbrtru #hibernate.connection.password hibbrtru -## Oracle 10g -#hibernate.dialect org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect -#hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver -#hibernate.connection.url jdbc:oracle:thin:@oracle.geovise.com/ORCL -#hibernate.connection.username hbs -#hibernate.connection.password hbs +## +## GeoDb (H2 spatial extension) +## +#hibernate.dialect org.hibernate.spatial.dialect.h2geodb.GeoDBDialect +#hibernate.connection.driver_class org.h2.Driver +#hibernate.connection.url jdbc:h2:mem:testhbs;DB_CLOSE_DELAY=-1;MVCC=true +#hibernate.connection.username sa +#hibernate.connection.password sa + +## ## Oracle 11g ## #hibernate.dialect org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect @@ -65,8 +69,23 @@ hibernate.connection.username sa #hibernate.connection.username HBS #hibernate.connection.password HBS +## +## Test Oracle ogc_strict property setting +## +#hibernate.spatial.ogc_strict false -## Sql Server 2008 +## +## Oracle 10g +## +#hibernate.dialect org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect +#hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver +#hibernate.connection.url jdbc:oracle:thin:@oracle.geovise.com/ORCL +#hibernate.connection.username hbs +#hibernate.connection.password hbs + + +## +## MS SQL Server dialect ## #hibernate.dialect org.hibernate.spatial.dialect.sqlserver.SqlServer2008SpatialDialect #hibernate.connection.driver_class com.microsoft.sqlserver.jdbc.SQLServerDriver @@ -84,19 +103,20 @@ hibernate.connection.username sa #hibernate.connection.username hibernate #hibernate.connection.password hibernate -#hibernate.dialect org.hibernate.spatial.dialect.mysql.MySQL5SpatialInnoDBDialect +## +## MySQL 5 InnoDDB dialect +## +#hibernate.dialect org.hibernate.spatial.dialect.mysql.MySQLSpatial5InnoDBDialect #hibernate.connection.driver_class com.mysql.jdbc.Driver #hibernate.connection.url jdbc:mysql://localhost/testhbs #hibernate.connection.username hibernate #hibernate.connection.password hibernate ## -##GeoDB dialect +## MySQL 5.6.1 dialect ## -#hibernate.dialect org.hibernate.spatial.dialect.h2geodb.GeoDBDialect -#hibernate.connection.driver_class org.h2.Driver -#hibernate.connection.url jdbc:h2:mem:testhbs;DB_CLOSE_DELAY=-1;MVCC=true -#hibernate.connection.username sa -#hibernate.connection.password sa - - +#hibernate.dialect org.hibernate.spatial.dialect.mysql.MySQL56SpatialDialect +#hibernate.connection.driver_class com.mysql.jdbc.Driver +#hibernate.connection.url jdbc:mysql://172.16.1.130/test +#hibernate.connection.username HBS +#hibernate.connection.password HBS diff --git a/hibernate-spatial/src/test/resources/log4j.properties b/hibernate-spatial/src/test/resources/log4j.properties index 3b9f13e13a..33870747ef 100644 --- a/hibernate-spatial/src/test/resources/log4j.properties +++ b/hibernate-spatial/src/test/resources/log4j.properties @@ -5,5 +5,6 @@ log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n log4j.rootLogger=info, stdout +log4j.logger.org.hibernate.SQL=DEBUG log4j.logger.org.hibernate.spatial=debug