HHH-14800 Use TypeContributor to register spatial types

This commit is contained in:
Karel Maesen 2021-07-19 22:52:19 +02:00
parent 04491e6775
commit 0b9de79a7d
10 changed files with 97 additions and 37 deletions

View File

@ -148,7 +148,7 @@ ext {
'connection.init_sql' : '' 'connection.init_sql' : ''
], ],
postgis : [ postgis : [
'db.dialect' : 'org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect', 'db.dialect' : 'org.hibernate.dialect.PostgreSQLDialect',
'jdbc.driver': 'org.postgresql.Driver', 'jdbc.driver': 'org.postgresql.Driver',
'jdbc.user' : 'hibernate_orm_test', 'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test', 'jdbc.pass' : 'hibernate_orm_test',

View File

@ -111,6 +111,8 @@ public class PostgreSQLDialect extends Dialect {
registerColumnType( Types.LONGVARCHAR, "text" ); registerColumnType( Types.LONGVARCHAR, "text" );
registerColumnType( Types.LONGNVARCHAR, "text" ); registerColumnType( Types.LONGNVARCHAR, "text" );
registerColumnType( 5432, "geometry" );
if ( getVersion() >= 820 ) { if ( getVersion() >= 820 ) {
registerColumnType( PostgresUUIDType.INSTANCE.getJdbcTypeDescriptor().getDefaultSqlTypeCode(), "uuid" ); registerColumnType( PostgresUUIDType.INSTANCE.getJdbcTypeDescriptor().getDefaultSqlTypeCode(), "uuid" );

View File

@ -8,6 +8,7 @@
package org.hibernate.spatial; package org.hibernate.spatial;
import org.jboss.logging.BasicLogger; import org.jboss.logging.BasicLogger;
import org.jboss.logging.Logger;
import org.jboss.logging.annotations.LogMessage; import org.jboss.logging.annotations.LogMessage;
import org.jboss.logging.annotations.Message; import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageLogger; import org.jboss.logging.annotations.MessageLogger;
@ -23,6 +24,14 @@ import static org.jboss.logging.Logger.Level.INFO;
@MessageLogger(projectCode = "HHH") @MessageLogger(projectCode = "HHH")
@ValidIdRange(min = 80000001, max = 80001000) @ValidIdRange(min = 80000001, max = 80001000)
public interface HSMessageLogger extends BasicLogger { public interface HSMessageLogger extends BasicLogger {
String LOGGER_NAME = "org.hibernate.spatial";
HSMessageLogger LOGGER = Logger.getMessageLogger( HSMessageLogger.class, LOGGER_NAME );
boolean TRACE_ENABLED = LOGGER.isTraceEnabled();
boolean DEBUG_ENABLED = LOGGER.isDebugEnabled();
@LogMessage(level = INFO) @LogMessage(level = INFO)
@Message(value = "hibernate-spatial integration enabled : %s", id = 80000001) @Message(value = "hibernate-spatial integration enabled : %s", id = 80000001)
void spatialEnabled(boolean enabled); void spatialEnabled(boolean enabled);
@ -31,4 +40,8 @@ public interface HSMessageLogger extends BasicLogger {
@Message(value = "hibernate-spatial using Connection Finder for creating Oracle types : %s", id = 80000002) @Message(value = "hibernate-spatial using Connection Finder for creating Oracle types : %s", id = 80000002)
void connectionFinder(String className); void connectionFinder(String className);
@LogMessage(level = INFO) //maybe should be DEBUG?
@Message(value = "hibernate-spatial using type contributions from : %s", id = 80000003)
void typeContributions(String source);
} }

View File

@ -15,15 +15,22 @@
package org.hibernate.spatial.type; package org.hibernate.spatial.type;
import org.hibernate.boot.model.TypeContributions; import org.hibernate.boot.model.TypeContributions;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor; import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
import org.hibernate.spatial.GeolatteGeometryType; import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.JTSGeometryJavaTypeDescriptor; import org.hibernate.spatial.JTSGeometryJavaTypeDescriptor;
import org.hibernate.spatial.JTSGeometryType; import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.dialect.postgis.PGGeometryTypeDescriptor; import org.hibernate.spatial.dialect.postgis.PGGeometryTypeDescriptor;
public class PostgisTypeContributor implements SpatialTypeContributorImplementor{ public class PostgreSQLDialectTypeContributor extends SpatialTypeContributorImplementor{
PostgreSQLDialectTypeContributor(ServiceRegistry serviceRegistry) {
super( serviceRegistry );
}
public void contribute(TypeContributions typeContributions) { public void contribute(TypeContributions typeContributions) {
HSMessageLogger.LOGGER.typeContributions( this.getClass().getCanonicalName() );
typeContributions.contributeType( new GeolatteGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_1 ) ); typeContributions.contributeType( new GeolatteGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_1 ) );
typeContributions.contributeType( new JTSGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_1 ) ); typeContributions.contributeType( new JTSGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_1 ) );

View File

@ -9,25 +9,17 @@ package org.hibernate.spatial.type;
import org.hibernate.boot.model.TypeContributions; import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.TypeContributor; import org.hibernate.boot.model.TypeContributor;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.JTSGeometryJavaTypeDescriptor;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.dialect.postgis.PGGeometryTypeDescriptor;
public class SpatialTypeContributor implements TypeContributor { public class SpatialTypeContributor implements TypeContributor {
@Override @Override
public void contribute( public void contribute(
TypeContributions typeContributions, ServiceRegistry serviceRegistry) { TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
SpatialTypeContributorImplementor contributorImplementor = TypeContributorResolver.resolve( serviceRegistry );
typeContributions.contributeType( new GeolatteGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_1 ) ); if (contributorImplementor != null) {
typeContributions.contributeType( new JTSGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_1 ) ); contributorImplementor.contribute( typeContributions );
}
typeContributions.contributeJavaTypeDescriptor( GeolatteGeometryJavaTypeDescriptor.INSTANCE );
typeContributions.contributeJavaTypeDescriptor( JTSGeometryJavaTypeDescriptor.INSTANCE );
} }
} }

View File

@ -7,5 +7,23 @@
package org.hibernate.spatial.type; package org.hibernate.spatial.type;
public interface SpatialTypeContributorImplementor { import org.hibernate.boot.model.TypeContributions;
import org.hibernate.service.ServiceRegistry;
/**
* Internal contract for TypeContributor
*/
abstract class SpatialTypeContributorImplementor {
private final ServiceRegistry serviceRegistryegistry;
SpatialTypeContributorImplementor(ServiceRegistry serviceRegistry) {
this.serviceRegistryegistry = serviceRegistry;
}
abstract void contribute(TypeContributions typeContributions);
ServiceRegistry getServiceRegistryegistry() {
return serviceRegistryegistry;
}
} }

View File

@ -7,5 +7,23 @@
package org.hibernate.spatial.type; package org.hibernate.spatial.type;
public class TypeContributorResolver { import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.service.ServiceRegistry;
class TypeContributorResolver {
private TypeContributorResolver() {
}
static SpatialTypeContributorImplementor resolve(ServiceRegistry serviceRegistry) {
JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class );
Dialect dialect = jdbcServices.getDialect();
if ( dialect.getClass().isAssignableFrom( PostgreSQLDialect.class ) ) {
return new PostgreSQLDialectTypeContributor( serviceRegistry );
}
return null;
}
} }

View File

@ -0,0 +1,8 @@
#
# 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>.
#
org.hibernate.spatial.type.SpatialTypeContributor

View File

@ -16,14 +16,17 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.spatial.testing.GeometryEquality; import org.hibernate.spatial.testing.GeometryEquality;
import org.hibernate.spatial.testing.datareader.TestDataElement; import org.hibernate.spatial.testing.datareader.TestDataElement;
import org.hibernate.spatial.testing.domain.GeomEntity;
import org.hibernate.spatial.testing.domain.SpatialDomainModel; import org.hibernate.spatial.testing.domain.SpatialDomainModel;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
/** /**
@ -50,6 +53,12 @@ public abstract class AbstractTestStoreRetrieve<G, E extends GeomEntityLike<G>>
scope.inTransaction( this::retrieveAndCompare ); scope.inTransaction( this::retrieveAndCompare );
} }
@AfterEach
public void cleanTables(SessionFactoryScope scope) {
scope.inTransaction( session -> session.createQuery( "delete from " + this.getGeomEntityClass()
.getCanonicalName() ).executeUpdate() );
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void retrieveAndCompare(SessionImplementor session) { private void retrieveAndCompare(SessionImplementor session) {
Query query = session.createQuery( "from " + this.getGeomEntityClass().getCanonicalName() ); Query query = session.createQuery( "from " + this.getGeomEntityClass().getCanonicalName() );
@ -63,26 +72,12 @@ public abstract class AbstractTestStoreRetrieve<G, E extends GeomEntityLike<G>>
} }
@Test @Test
public void testStoringNullGeometries() { public void testStoringNullGeometries(SessionFactoryScope scope) {
storeNullGeometry(); scope.inTransaction( this::storeNullGeometry );
retrieveNullGeometry(); scope.inTransaction( this::retrieveAndCompareNullGeometry );
}
private String createFailureMessage(int id, G storedGeometry, G retrievedGeometry) {
String expectedText = ( storedGeometry != null ? storedGeometry.toString() : "NULL" );
String retrievedText = ( retrievedGeometry != null ? retrievedGeometry.toString() : "NULL" );
return String.format(
"Equality testsuite-suite failed for %d.%nExpected: %s%nReceived:%s",
id,
expectedText,
retrievedText
);
} }
private void storeTestObjects(SessionImplementor session) { private void storeTestObjects(SessionImplementor session) {
// Every testsuite-suite instance is committed seperately
// to improve feedback in case of failure
for ( TestDataElement element : testData ) { for ( TestDataElement element : testData ) {
E entity = createFrom( element, session.getJdbcServices().getDialect() ); E entity = createFrom( element, session.getJdbcServices().getDialect() );
stored.put( entity.getId(), entity ); stored.put( entity.getId(), entity );
@ -90,11 +85,17 @@ public abstract class AbstractTestStoreRetrieve<G, E extends GeomEntityLike<G>>
} }
} }
private void storeNullGeometry(SessionImplementor session) {
private void storeNullGeometry() { GeomEntity entity = new GeomEntity();
entity.setId( 1 );
entity.setType( "NULL Test" );
session.save( entity );
} }
private void retrieveNullGeometry() { private void retrieveAndCompareNullGeometry(SessionImplementor session) {
GeomEntity entity = session.createQuery( "from GeomEntity", GeomEntity.class ).getResultList().get( 0 );
assertEquals( "NULL Test", entity.getType() );
assertEquals( 1, entity.getId() );
assertNull( entity.getGeom() );
} }
} }

View File

@ -6,6 +6,7 @@
# See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. # See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
# #
# Default unit/integration test config. # Default unit/integration test config.
hibernate.show_sql=true hibernate.show_sql=true
hibernate.max_fetch_depth=5 hibernate.max_fetch_depth=5
hibernate.dialect=@db.dialect@ hibernate.dialect=@db.dialect@