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' : ''
],
postgis : [
'db.dialect' : 'org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect',
'db.dialect' : 'org.hibernate.dialect.PostgreSQLDialect',
'jdbc.driver': 'org.postgresql.Driver',
'jdbc.user' : '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.LONGNVARCHAR, "text" );
registerColumnType( 5432, "geometry" );
if ( getVersion() >= 820 ) {
registerColumnType( PostgresUUIDType.INSTANCE.getJdbcTypeDescriptor().getDefaultSqlTypeCode(), "uuid" );

View File

@ -8,6 +8,7 @@
package org.hibernate.spatial;
import org.jboss.logging.BasicLogger;
import org.jboss.logging.Logger;
import org.jboss.logging.annotations.LogMessage;
import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageLogger;
@ -23,6 +24,14 @@ import static org.jboss.logging.Logger.Level.INFO;
@MessageLogger(projectCode = "HHH")
@ValidIdRange(min = 80000001, max = 80001000)
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)
@Message(value = "hibernate-spatial integration enabled : %s", id = 80000001)
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)
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;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
import org.hibernate.spatial.GeolatteGeometryType;
import org.hibernate.spatial.HSMessageLogger;
import org.hibernate.spatial.JTSGeometryJavaTypeDescriptor;
import org.hibernate.spatial.JTSGeometryType;
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) {
HSMessageLogger.LOGGER.typeContributions( this.getClass().getCanonicalName() );
typeContributions.contributeType( new GeolatteGeometryType( 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.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.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 {
@Override
public void contribute(
TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
SpatialTypeContributorImplementor contributorImplementor = TypeContributorResolver.resolve( serviceRegistry );
typeContributions.contributeType( new GeolatteGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_1 ) );
typeContributions.contributeType( new JTSGeometryType( PGGeometryTypeDescriptor.INSTANCE_WKB_1 ) );
if (contributorImplementor != null) {
contributorImplementor.contribute( typeContributions );
}
typeContributions.contributeJavaTypeDescriptor( GeolatteGeometryJavaTypeDescriptor.INSTANCE );
typeContributions.contributeJavaTypeDescriptor( JTSGeometryJavaTypeDescriptor.INSTANCE );
}
}

View File

@ -7,5 +7,23 @@
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;
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.spatial.testing.GeometryEquality;
import org.hibernate.spatial.testing.datareader.TestDataElement;
import org.hibernate.spatial.testing.domain.GeomEntity;
import org.hibernate.spatial.testing.domain.SpatialDomainModel;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
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 );
}
@AfterEach
public void cleanTables(SessionFactoryScope scope) {
scope.inTransaction( session -> session.createQuery( "delete from " + this.getGeomEntityClass()
.getCanonicalName() ).executeUpdate() );
}
@SuppressWarnings("unchecked")
private void retrieveAndCompare(SessionImplementor session) {
Query query = session.createQuery( "from " + this.getGeomEntityClass().getCanonicalName() );
@ -63,26 +72,12 @@ public abstract class AbstractTestStoreRetrieve<G, E extends GeomEntityLike<G>>
}
@Test
public void testStoringNullGeometries() {
storeNullGeometry();
retrieveNullGeometry();
}
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
);
public void testStoringNullGeometries(SessionFactoryScope scope) {
scope.inTransaction( this::storeNullGeometry );
scope.inTransaction( this::retrieveAndCompareNullGeometry );
}
private void storeTestObjects(SessionImplementor session) {
// Every testsuite-suite instance is committed seperately
// to improve feedback in case of failure
for ( TestDataElement element : testData ) {
E entity = createFrom( element, session.getJdbcServices().getDialect() );
stored.put( entity.getId(), entity );
@ -90,11 +85,17 @@ public abstract class AbstractTestStoreRetrieve<G, E extends GeomEntityLike<G>>
}
}
private void storeNullGeometry() {
private void storeNullGeometry(SessionImplementor session) {
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>.
#
# Default unit/integration test config.
hibernate.show_sql=true
hibernate.max_fetch_depth=5
hibernate.dialect=@db.dialect@