HHH-7132 - Oracle Spatial Dialect locates ConnectionFinder using Registry

This commit is contained in:
Karel Maesen 2016-02-20 17:50:13 +01:00
parent be425d2308
commit 8d2de0beaa
16 changed files with 128 additions and 327 deletions

View File

@ -0,0 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
jdbcDependency "com.oracle.jdbc:ojdbc6:11.1.0.7.0"

View File

@ -0,0 +1,25 @@
#
# Hibernate, Relational Persistence for Idiomatic Java
#
# License: GNU Lesser General Public License (LGPL), version 2.1 or later.
# See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
#
hibernate.dialect org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect
hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver
hibernate.connection.url jdbc:oracle:thin:@ec2-54-216-171-204.eu-west-1.compute.amazonaws.com:1521/ORCL
hibernate.connection.username hibspa
hibernate.connection.password L9un5Bh6
## uncommenting this will fail a unit test!!
hibernate.spatial.connection_finder org.hibernate.spatial.dialect.oracle.TestConnectionFinder
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

View File

@ -4,4 +4,4 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
jdbcDependency "com.oracle.jdbc:ojdbc6:11.2.0.3"
jdbcDependency "com.oracle.jdbc:ojdbc6:11.1.0.7.0"

View File

@ -7,7 +7,7 @@
hibernate.dialect org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect
hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver
hibernate.connection.url jdbc:oracle:thin:@hibernatespatial-oracle.cctaez8ywvn2.eu-west-1.rds.amazonaws.com:1521/ORCL
hibernate.connection.url jdbc:oracle:thin:@ec2-54-216-171-204.eu-west-1.compute.amazonaws.com:1521/ORCL
hibernate.connection.username hibspa
hibernate.connection.password L9un5Bh6

View File

@ -47,10 +47,13 @@ dependencies {
// for test runtime
transitive = true
}
testRuntime( libraries.expression_language_api )
testRuntime( libraries.expression_language_impl )
testRuntime('jaxen:jaxen:1.1')
testRuntime(libraries.javassist)
// matrixRuntime( 'jaxen:jaxen:1.1' )
}
sourceSets.test.resources {

View File

@ -26,4 +26,9 @@ public interface HSMessageLogger extends BasicLogger {
@LogMessage(level = INFO)
@Message(value = "hibernate-spatial integration enabled : %s", id = 80000001)
void spatialEnabled(boolean enabled);
@LogMessage(level = INFO)
@Message(value = "hibernate-spatial using Connection Finder for creating Oracle types : %s", id = 80000002)
void connectionFinder(String className);
}

View File

@ -1,80 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial;
import org.geolatte.geom.codec.db.oracle.ConnectionFinder;
import java.io.Serializable;
import org.jboss.logging.Logger;
/**
* 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 implements Serializable {
private static final HSMessageLogger LOG = Logger.getMessageLogger(
HSMessageLogger.class,
HibernateSpatialConfiguration.class.getName()
);
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.debugf( "Setting OGC_STRICT mode for Oracle Spatial dialect to %s.", ogcStrict );
}
if ( connectionFinder != null ) {
this.connectionFinder = connectionFinder;
LOG.debugf(
"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";
}
}

View File

@ -0,0 +1,30 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial;
import org.geolatte.geom.codec.db.oracle.ConnectionFinder;
import java.io.Serializable;
import org.jboss.logging.Logger;
/**
* Hibernate Spatial specific configuration settings.
*
* @author Karel Maesen, Geovise BVBA
* creation-date: 8/16/13
*/
public class HibernateSpatialConfigurationSettings implements Serializable {
/**
* The canonical class name to use as Oracle ConnectionFinder implementation.
*/
public static final String CONNECTION_FINDER = "hibernate.spatial.connection_finder";
}

View File

@ -12,18 +12,22 @@ import java.sql.Types;
import java.util.List;
import org.geolatte.geom.codec.db.oracle.ConnectionFinder;
import org.geolatte.geom.codec.db.oracle.DefaultConnectionFinder;
import org.geolatte.geom.codec.db.oracle.OracleJDBCTypeFactory;
import org.jboss.logging.Logger;
import org.hibernate.QueryException;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.dialect.Oracle10gDialect;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.HibernateSpatialConfiguration;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.HibernateSpatialConfigurationSettings;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.SpatialAnalysis;
import org.hibernate.spatial.SpatialDialect;
@ -41,27 +45,19 @@ import org.hibernate.type.Type;
public class OracleSpatial10gDialect extends Oracle10gDialect implements SpatialDialect, Serializable {
private final boolean isOgcStrict;
private final ConnectionFinder connectionFinder;
/**
* Constructs the dialect with a default configuration
*/
public OracleSpatial10gDialect() {
this( new HibernateSpatialConfiguration() );
}
private static final HSMessageLogger log = Logger.getMessageLogger(
HSMessageLogger.class,
OracleSpatial10gDialect.class.getName()
);
/**
* Constructs the dialect with the specified configuration
*
* @param config the {@code HibernateSpatialConfiguration} that configures this dialect.
*/
public OracleSpatial10gDialect(HibernateSpatialConfiguration config) {
public OracleSpatial10gDialect() {
super();
this.isOgcStrict = config.isOgcStrictMode();
final ConnectionFinder finder = config.getConnectionFinder();
this.connectionFinder = finder == null ? new DefaultConnectionFinder() : finder;
this.isOgcStrict = true;
// register geometry type
registerColumnType( Types.STRUCT, "MDSYS.SDO_GEOMETRY" );
@ -158,15 +154,26 @@ public class OracleSpatial10gDialect extends Oracle10gDialect implements Spatial
serviceRegistry
);
final ConfigurationService cfgService = serviceRegistry.getService( ConfigurationService.class );
final StrategySelector strategySelector = serviceRegistry.getService( StrategySelector.class );
final ConnectionFinder connectionFinder = strategySelector.resolveStrategy(
ConnectionFinder.class,
cfgService.getSetting( HibernateSpatialConfigurationSettings.CONNECTION_FINDER, String.class, "org.geolatte.geom.codec.db.oracle.DefaultConnectionFinder" )
);
log.connectionFinder( connectionFinder.getClass().getCanonicalName() );
final SDOGeometryTypeDescriptor sdoGeometryTypeDescriptor = new SDOGeometryTypeDescriptor(
new OracleJDBCTypeFactory(
this.connectionFinder
connectionFinder
)
);
typeContributions.contributeType( new GeolatteGeometryType( sdoGeometryTypeDescriptor ) );
typeContributions.contributeType( new JTSGeometryType( sdoGeometryTypeDescriptor ) );
}
String getNativeSpatialRelateSQL(String arg1, String arg2, int spatialRelation) {
@ -418,16 +425,6 @@ public class OracleSpatial10gDialect extends Oracle10gDialect implements Spatial
return isOgcStrict;
}
/**
* Reports the ConnectionFinder used by this Dialect (or rather its associated TypeDescriptor).
* <p/>
* This method is mainly used for testing purposes.
*
* @return the ConnectionFinder in use
*/
public ConnectionFinder getConnectionFinder() {
return connectionFinder;
}
@Override
public boolean supportsFiltering() {

View File

@ -1,50 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.integration;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource;
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 special handling of the {@code OracleSpatial10gDialect}.
*
* @author Karel Maesen, Geovise BVBA
* creation-date: 8/23/13
*/
public class SpatialDialectFactory extends DialectFactoryImpl {
private final HibernateSpatialConfiguration spatialConfig;
/**
* Constructs an instance with the specified configuration
*
* @param spatialConfig the spatial configuration to use.
*/
public SpatialDialectFactory(HibernateSpatialConfiguration spatialConfig) {
super();
this.spatialConfig = spatialConfig;
}
@Override
public Dialect buildDialect(Map configValues, DialectResolutionInfoSource resolutionInfoSource) throws HibernateException {
final Dialect dialect = super.buildDialect( configValues, resolutionInfoSource );
if (dialect instanceof OracleSpatial10gDialect) {
return new OracleSpatial10gDialect( spatialConfig );
}
else {
return dialect;
}
}
}

View File

@ -1,56 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.integration;
import java.util.Map;
import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.dialect.spi.DialectFactory;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.spatial.HibernateSpatialConfiguration;
import org.geolatte.geom.codec.db.oracle.ConnectionFinder;
import static org.hibernate.engine.config.spi.StandardConverters.BOOLEAN;
import static org.hibernate.spatial.HibernateSpatialConfiguration.AvailableSettings.CONNECTION_FINDER;
import static org.hibernate.spatial.HibernateSpatialConfiguration.AvailableSettings.OGC_STRICT;
/**
* The {@code StandardServiceInitiator} for Hibernate Spatial's specialized DialectFactory.
*
* @author Karel Maesen, Geovise BVBA
* @author Steve Ebersole
*/
public class SpatialDialectFactoryInitiator implements StandardServiceInitiator<DialectFactory> {
/**
* Singleton access
*/
public static final SpatialDialectFactoryInitiator INSTANCE = new SpatialDialectFactoryInitiator();
@Override
public Class<DialectFactory> getServiceInitiated() {
return DialectFactory.class;
}
@Override
public SpatialDialectFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
final ConfigurationService cfgService = registry.getService( ConfigurationService.class );
final StrategySelector strategySelector = registry.getService( StrategySelector.class );
final HibernateSpatialConfiguration spatialConfig = new HibernateSpatialConfiguration(
cfgService.getSetting( OGC_STRICT, BOOLEAN, null ),
strategySelector.resolveStrategy(
ConnectionFinder.class,
cfgService.getSettings().get( CONNECTION_FINDER )
)
);
return new SpatialDialectFactory( spatialConfig );
}
}

View File

@ -21,12 +21,6 @@ public class SpatialInitializer implements ServiceContributor {
public void contribute(StandardServiceRegistryBuilder serviceRegistryBuilder) {
final SpatialService spatialService = new SpatialService( serviceRegistryBuilder );
serviceRegistryBuilder.addService( SpatialService.class, spatialService );
if ( !spatialService.isEnabled() ) {
return;
}
serviceRegistryBuilder.addInitiator( SpatialDialectFactoryInitiator.INSTANCE );
}
}

View File

@ -11,6 +11,7 @@ import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.Service;
import org.hibernate.spatial.HSMessageLogger;
import org.jboss.logging.Logger;
/**
@ -39,11 +40,11 @@ public class SpatialService implements Service {
serviceRegistryBuilder.getSettings(),
true
);
log.spatialEnabled( integrationEnabled );
}
public boolean isEnabled() {
return integrationEnabled;
}
}

View File

@ -1,19 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.dialect.oracle;
import java.sql.Connection;
import org.geolatte.geom.codec.db.oracle.ConnectionFinder;
public class MockConnectionFinder implements ConnectionFinder {
@Override
public Connection find(Connection subject) {
return null;
}
}

View File

@ -1,85 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.spatial.dialect.oracle;
import org.geolatte.geom.codec.db.oracle.ConnectionFinder;
import org.geolatte.geom.codec.db.oracle.DefaultConnectionFinder;
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 );
}
}

View File

@ -0,0 +1,29 @@
package org.hibernate.spatial.dialect.oracle;
import java.sql.Connection;
import org.geolatte.geom.codec.db.oracle.ConnectionFinder;
import org.geolatte.geom.codec.db.oracle.DefaultConnectionFinder;
/**
* Created by Karel Maesen, Geovise BVBA on 20/02/16.
*/
public class TestConnectionFinder implements ConnectionFinder {
final private ConnectionFinder internal = new DefaultConnectionFinder();
/**
* Find an instance of Connection that can be cast to an {@code OracleConnection} instance.
*
* @param conn the object that is being searched for an OracleConnection
*
* @return the object sought
*
* @throws RuntimeException thrown when the feature can be found;
*/
@Override
public Connection find(Connection conn) {
return internal.find( conn );
}
}