HHH-12410 - Cannot use AttributeConverter with spatial types
HHH-12443 - Introduce TypeConfiguration
This commit is contained in:
parent
216ad13e6c
commit
c14180ea5b
|
@ -24,6 +24,8 @@ ext {
|
|||
javassistVersion = '3.22.0-GA'
|
||||
byteBuddyVersion = '1.8.0' // Now with JDK10 compatibility and preliminary support for JDK11
|
||||
|
||||
geolatteVersion = '1.3.0'
|
||||
|
||||
// Wildfly version targeted by module ZIP; Arquillian/Shrinkwrap versions used for CDI testing and testing the module ZIP
|
||||
wildflyVersion = '12.0.0.Final'
|
||||
arquillianVersion = '1.1.11.Final'
|
||||
|
@ -31,6 +33,8 @@ ext {
|
|||
shrinkwrapDescriptorsVersion = '2.0.0-alpha-8'
|
||||
wildflyArquillianContainerVersion = '2.0.0.Final'
|
||||
|
||||
jodaTimeVersion = '2.3'
|
||||
|
||||
libraries = [
|
||||
// Ant
|
||||
ant: 'org.apache.ant:ant:1.8.2',
|
||||
|
@ -74,6 +78,8 @@ ext {
|
|||
jaxb2_jaxb: 'org.jvnet.jaxb2_commons:jaxb2-basics-jaxb:2.2.4-1',
|
||||
jaxb2_jaxb_xjc: 'org.jvnet.jaxb2_commons:jaxb2-basics-jaxb-xjc:2.2.4-1',
|
||||
|
||||
geolatte: "org.geolatte:geolatte-geom:${geolatteVersion}",
|
||||
|
||||
// Animal Sniffer Ant Task and Java 1.6 API signature file
|
||||
// not using 1.9 for the time being due to MANIMALSNIFFER-34
|
||||
animal_sniffer: 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.13',
|
||||
|
@ -105,6 +111,8 @@ ext {
|
|||
db2: 'com.ibm.db2:db2jcc:10.5',
|
||||
hana: 'com.sap.db.jdbc:ngdbc:2.2.1', // for HANA 1 the minimum required client version is 1.120.20
|
||||
|
||||
jodaTime: "joda-time:joda-time:${jodaTimeVersion}",
|
||||
|
||||
informix: 'com.ibm.informix:jdbc:4.10.7.20160517',
|
||||
jboss_jta: "org.jboss.jbossts:jbossjta:4.16.4.Final",
|
||||
xapool: "com.experlog:xapool:1.5.0",
|
||||
|
|
|
@ -69,7 +69,7 @@ dependencies {
|
|||
testCompile( libraries.classmate )
|
||||
testCompile( libraries.mockito )
|
||||
testCompile( libraries.mockito_inline )
|
||||
testCompile( 'joda-time:joda-time:2.3' )
|
||||
testCompile( libraries.jodaTime )
|
||||
|
||||
testCompile( libraries.cdi ) {
|
||||
// we need to force it to make sure we influence the one coming from arquillian
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
package org.hibernate.boot.model;
|
||||
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.StandardBasicTypeTemplate;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -19,34 +21,56 @@ import org.hibernate.usertype.UserType;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface TypeContributions {
|
||||
TypeConfiguration getTypeConfiguration();
|
||||
|
||||
/**
|
||||
* Add the JavaTypeDescriptor to the {@link TypeConfiguration}'s
|
||||
* {@link JavaTypeDescriptorRegistry}
|
||||
*/
|
||||
void contributeJavaTypeDescriptor(JavaTypeDescriptor descriptor);
|
||||
|
||||
/**
|
||||
* Add the JavaTypeDescriptor to the {@link TypeConfiguration}'s
|
||||
* {@link JavaTypeDescriptorRegistry}
|
||||
*/
|
||||
void contributeSqlTypeDescriptor(SqlTypeDescriptor descriptor);
|
||||
|
||||
void contributeType(BasicType type);
|
||||
|
||||
/**
|
||||
* @deprecated (since 5.3) It will be replaced by {@link #contributeType(BasicType)}
|
||||
* but do not move to it before 6.0
|
||||
* @deprecated (since 5.3) Use {@link #contributeType(BasicType)} instead. Basic
|
||||
* types will be defined and handled much differently in 6.0 based on a combination
|
||||
* of {@link JavaTypeDescriptor}, {@link SqlTypeDescriptor} and a concept of a "value
|
||||
* converter" (a JPA AttributeConverter, an enum value resolver, etc). To get as
|
||||
* close as possible in 5.3 use existing {@link JavaTypeDescriptor} and
|
||||
* {@link SqlTypeDescriptor} implementations (or write your own for custom types)
|
||||
* and use {@link StandardBasicTypeTemplate} to combine those with
|
||||
* registration keys and call {@link #contributeType(BasicType)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
void contributeType(BasicType type, String... keys);
|
||||
|
||||
/**
|
||||
* @deprecated (since 5.3) It will be replaced by {@link #contributeType(BasicType)}
|
||||
* but do not move to it before 6.0
|
||||
* @deprecated (since 5.3) Use {@link #contributeType(BasicType)} instead.
|
||||
* {@link UserType}, as currently defined, will be done very differently in 6.0.
|
||||
* In most cases a {@link UserType} can be simply replaced with proper
|
||||
* {@link JavaTypeDescriptor}. To get as close as possible to 6.0 in 5.3 use
|
||||
* existing {@link JavaTypeDescriptor} and {@link SqlTypeDescriptor}
|
||||
* implementations (or write your own for custom impls) and use
|
||||
* {@link StandardBasicTypeTemplate} to combine those with registration keys
|
||||
* and call {@link #contributeType(BasicType)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
void contributeType(UserType type, String... keys);
|
||||
|
||||
/**
|
||||
* @deprecated (since 5.3) It will be replaced by {@link #contributeType(BasicType)}
|
||||
* but do not move to it before 6.0
|
||||
* @deprecated (since 5.3) Use {@link #contributeType(BasicType)} instead.
|
||||
* {@link CompositeUserType}, as currently defined, will be done very differently
|
||||
* in 6.0. {@link CompositeUserType} should be replaced with a normal Hibernate
|
||||
* component or JPA embeddable (different names, same thing. This embeddable
|
||||
* may contain, in turn, custom types that should be handled as described on these
|
||||
* methods
|
||||
*/
|
||||
@Deprecated
|
||||
void contributeType(CompositeUserType type, String... keys);
|
||||
|
||||
/*
|
||||
* Add the JavaTypeDescriptor to the
|
||||
* @param descriptor
|
||||
*/
|
||||
void contributeJavaTypeDescriptor(JavaTypeDescriptor descriptor);
|
||||
|
||||
void contributeSqlTypeDescriptor(SqlTypeDescriptor descriptor);
|
||||
|
||||
TypeConfiguration getTypeConfiguration();
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
package org.hibernate.boot.model.convert.spi;
|
||||
|
||||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||
|
||||
/**
|
||||
* Access to information that implementors of
|
||||
|
|
|
@ -64,7 +64,7 @@ public class StandardServiceRegistryBuilder {
|
|||
* @param bootstrapServiceRegistry Provided bootstrap registry to use.
|
||||
*/
|
||||
public StandardServiceRegistryBuilder(BootstrapServiceRegistry bootstrapServiceRegistry) {
|
||||
this( bootstrapServiceRegistry, LoadedConfig.baseline() );
|
||||
this( bootstrapServiceRegistry, LoadedConfig.baseline() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,7 +72,9 @@ public class StandardServiceRegistryBuilder {
|
|||
*
|
||||
* @param bootstrapServiceRegistry Provided bootstrap registry to use.
|
||||
*/
|
||||
public StandardServiceRegistryBuilder(BootstrapServiceRegistry bootstrapServiceRegistry, LoadedConfig loadedConfigBaseline) {
|
||||
public StandardServiceRegistryBuilder(
|
||||
BootstrapServiceRegistry bootstrapServiceRegistry,
|
||||
LoadedConfig loadedConfigBaseline) {
|
||||
this.settings = Environment.getProperties();
|
||||
this.bootstrapServiceRegistry = bootstrapServiceRegistry;
|
||||
this.configLoader = new ConfigLoader( bootstrapServiceRegistry );
|
||||
|
@ -103,7 +105,7 @@ public class StandardServiceRegistryBuilder {
|
|||
|
||||
/**
|
||||
* Read settings from a {@link java.util.Properties} file by resource name.
|
||||
*
|
||||
* <p>
|
||||
* Differs from {@link #configure()} and {@link #configure(String)} in that here we expect to read a
|
||||
* {@link java.util.Properties} file while for {@link #configure} we read the XML variant.
|
||||
*
|
||||
|
@ -114,7 +116,7 @@ public class StandardServiceRegistryBuilder {
|
|||
* @see #configure()
|
||||
* @see #configure(String)
|
||||
*/
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public StandardServiceRegistryBuilder loadProperties(String resourceName) {
|
||||
settings.putAll( configLoader.loadProperties( resourceName ) );
|
||||
return this;
|
||||
|
@ -122,7 +124,7 @@ public class StandardServiceRegistryBuilder {
|
|||
|
||||
/**
|
||||
* Read settings from a {@link java.util.Properties} file by File reference
|
||||
*
|
||||
* <p>
|
||||
* Differs from {@link #configure()} and {@link #configure(String)} in that here we expect to read a
|
||||
* {@link java.util.Properties} file while for {@link #configure} we read the XML variant.
|
||||
*
|
||||
|
@ -133,7 +135,7 @@ public class StandardServiceRegistryBuilder {
|
|||
* @see #configure()
|
||||
* @see #configure(String)
|
||||
*/
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public StandardServiceRegistryBuilder loadProperties(File file) {
|
||||
settings.putAll( configLoader.loadProperties( file ) );
|
||||
return this;
|
||||
|
@ -171,7 +173,7 @@ public class StandardServiceRegistryBuilder {
|
|||
return configure( configLoader.loadConfigXmlUrl( url ) );
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public StandardServiceRegistryBuilder configure(LoadedConfig loadedConfig) {
|
||||
aggregatedCfgXml.merge( loadedConfig );
|
||||
settings.putAll( loadedConfig.getConfigurationValues() );
|
||||
|
@ -187,7 +189,7 @@ public class StandardServiceRegistryBuilder {
|
|||
*
|
||||
* @return this, for method chaining
|
||||
*/
|
||||
@SuppressWarnings( {"unchecked", "UnusedDeclaration"})
|
||||
@SuppressWarnings({"unchecked", "UnusedDeclaration"})
|
||||
public StandardServiceRegistryBuilder applySetting(String settingName, Object value) {
|
||||
settings.put( settingName, value );
|
||||
return this;
|
||||
|
@ -200,7 +202,7 @@ public class StandardServiceRegistryBuilder {
|
|||
*
|
||||
* @return this, for method chaining
|
||||
*/
|
||||
@SuppressWarnings( {"unchecked", "UnusedDeclaration"})
|
||||
@SuppressWarnings({"unchecked", "UnusedDeclaration"})
|
||||
public StandardServiceRegistryBuilder applySettings(Map settings) {
|
||||
this.settings.putAll( settings );
|
||||
return this;
|
||||
|
@ -213,7 +215,7 @@ public class StandardServiceRegistryBuilder {
|
|||
*
|
||||
* @return this, for method chaining
|
||||
*/
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public StandardServiceRegistryBuilder addInitiator(StandardServiceInitiator initiator) {
|
||||
initiators.add( initiator );
|
||||
return this;
|
||||
|
@ -227,7 +229,7 @@ public class StandardServiceRegistryBuilder {
|
|||
*
|
||||
* @return this, for method chaining
|
||||
*/
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public StandardServiceRegistryBuilder addService(final Class serviceRole, final Service service) {
|
||||
providedServices.add( new ProvidedService( serviceRole, service ) );
|
||||
return this;
|
||||
|
@ -289,9 +291,11 @@ public class StandardServiceRegistryBuilder {
|
|||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void applyServiceContributingIntegrators() {
|
||||
for ( Integrator integrator : bootstrapServiceRegistry.getService( IntegratorService.class ).getIntegrators() ) {
|
||||
for ( Integrator integrator : bootstrapServiceRegistry.getService( IntegratorService.class )
|
||||
.getIntegrators() ) {
|
||||
if ( org.hibernate.integrator.spi.ServiceContributingIntegrator.class.isInstance( integrator ) ) {
|
||||
org.hibernate.integrator.spi.ServiceContributingIntegrator.class.cast( integrator ).prepareServices( this );
|
||||
org.hibernate.integrator.spi.ServiceContributingIntegrator.class.cast( integrator ).prepareServices(
|
||||
this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -332,4 +336,4 @@ public class StandardServiceRegistryBuilder {
|
|||
|
||||
( (StandardServiceRegistryImpl) serviceRegistry ).destroy();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -50,13 +50,13 @@ import org.hibernate.type.Type;
|
|||
import org.hibernate.type.descriptor.JdbcTypeNameMapper;
|
||||
import org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter;
|
||||
import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.descriptor.spi.JdbcRecommendedSqlTypeMappingContext;
|
||||
import org.hibernate.type.descriptor.sql.JdbcTypeJavaClassMappings;
|
||||
import org.hibernate.type.descriptor.sql.LobTypeMappings;
|
||||
import org.hibernate.type.descriptor.sql.NationalizedTypeMappings;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
import org.hibernate.usertype.DynamicParameterizedType;
|
||||
|
||||
|
@ -576,13 +576,13 @@ public class SimpleValue implements KeyValue {
|
|||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptorRegistry getJavaTypeDescriptorRegistry() {
|
||||
public org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry getJavaTypeDescriptorRegistry() {
|
||||
return metadata.getTypeConfiguration().getJavaTypeDescriptorRegistry();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
final JavaTypeDescriptor entityAttributeJavaTypeDescriptor = jpaAttributeConverter.getDomainJavaTypeDescriptor();
|
||||
final BasicJavaDescriptor entityAttributeJavaTypeDescriptor = jpaAttributeConverter.getDomainJavaTypeDescriptor();
|
||||
|
||||
|
||||
// build the SqlTypeDescriptor adapter ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -591,7 +591,11 @@ public class SimpleValue implements KeyValue {
|
|||
// corresponding to the AttributeConverter's declared "databaseColumnJavaType" (how we read that value out
|
||||
// of ResultSets). See JdbcTypeJavaClassMappings for details. Again, given example, this should return
|
||||
// VARCHAR/CHAR
|
||||
int jdbcTypeCode = JdbcTypeJavaClassMappings.INSTANCE.determineJdbcTypeCodeForJavaClass( jpaAttributeConverter.getRelationalJavaTypeDescriptor().getJavaType() );
|
||||
final SqlTypeDescriptor recommendedSqlType = jpaAttributeConverter.getRelationalJavaTypeDescriptor().getJdbcRecommendedSqlType(
|
||||
// todo (6.0) : handle the other JdbcRecommendedSqlTypeMappingContext methods
|
||||
metadata::getTypeConfiguration
|
||||
);
|
||||
int jdbcTypeCode = recommendedSqlType.getSqlType();
|
||||
if ( isLob() ) {
|
||||
if ( LobTypeMappings.INSTANCE.hasCorrespondingLobCode( jdbcTypeCode ) ) {
|
||||
jdbcTypeCode = LobTypeMappings.INSTANCE.getCorrespondingLobCode( jdbcTypeCode );
|
||||
|
|
|
@ -10,6 +10,7 @@ import javax.persistence.AttributeConverter;
|
|||
|
||||
import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
|
@ -20,8 +21,8 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
public class JpaAttributeConverterImpl<O,R> implements JpaAttributeConverter<O,R> {
|
||||
private final ManagedBean<AttributeConverter<O,R>> attributeConverterBean;
|
||||
private final JavaTypeDescriptor<AttributeConverter<O, R>> converterJavaTypeDescriptor;
|
||||
private final JavaTypeDescriptor<O> domainJavaTypeDescriptor;
|
||||
private final JavaTypeDescriptor<R> relationalJavaTypeDescriptor;
|
||||
private final BasicJavaDescriptor<O> domainJavaTypeDescriptor;
|
||||
private final BasicJavaDescriptor<R> relationalJavaTypeDescriptor;
|
||||
|
||||
public JpaAttributeConverterImpl(
|
||||
ManagedBean<AttributeConverter<O, R>> attributeConverterBean,
|
||||
|
@ -30,8 +31,13 @@ public class JpaAttributeConverterImpl<O,R> implements JpaAttributeConverter<O,R
|
|||
JavaTypeDescriptor<R> relationalJavaTypeDescriptor) {
|
||||
this.attributeConverterBean = attributeConverterBean;
|
||||
this.converterJavaTypeDescriptor = converterJavaTypeDescriptor;
|
||||
this.domainJavaTypeDescriptor = domainJavaTypeDescriptor;
|
||||
this.relationalJavaTypeDescriptor = relationalJavaTypeDescriptor;
|
||||
this.domainJavaTypeDescriptor = (BasicJavaDescriptor<O>) domainJavaTypeDescriptor;
|
||||
this.relationalJavaTypeDescriptor = (BasicJavaDescriptor<R>) relationalJavaTypeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedBean<AttributeConverter<O, R>> getConverterBean() {
|
||||
return attributeConverterBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,12 +56,12 @@ public class JpaAttributeConverterImpl<O,R> implements JpaAttributeConverter<O,R
|
|||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<O> getDomainJavaTypeDescriptor() {
|
||||
public BasicJavaDescriptor<O> getDomainJavaTypeDescriptor() {
|
||||
return domainJavaTypeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<R> getRelationalJavaTypeDescriptor() {
|
||||
public BasicJavaDescriptor<R> getRelationalJavaTypeDescriptor() {
|
||||
return relationalJavaTypeDescriptor;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ package org.hibernate.metamodel.model.convert.spi;
|
|||
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
|
@ -17,6 +19,9 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
*/
|
||||
public interface JpaAttributeConverter<O,R> extends BasicValueConverter<O,R> {
|
||||
JavaTypeDescriptor<AttributeConverter<O,R>> getConverterJavaTypeDescriptor();
|
||||
JavaTypeDescriptor<O> getDomainJavaTypeDescriptor();
|
||||
JavaTypeDescriptor<R> getRelationalJavaTypeDescriptor();
|
||||
|
||||
ManagedBean<AttributeConverter<O,R>> getConverterBean();
|
||||
|
||||
BasicJavaDescriptor<O> getDomainJavaTypeDescriptor();
|
||||
BasicJavaDescriptor<R> getRelationalJavaTypeDescriptor();
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ package org.hibernate.service;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ServiceRegistry {
|
||||
public interface ServiceRegistry extends AutoCloseable {
|
||||
/**
|
||||
* Retrieve this registry's parent registry.
|
||||
*
|
||||
|
@ -56,4 +56,6 @@ public interface ServiceRegistry {
|
|||
return service;
|
||||
}
|
||||
|
||||
@Override
|
||||
void close();
|
||||
}
|
||||
|
|
|
@ -25,6 +25,11 @@ public interface ServiceRegistryImplementor extends ServiceRegistry {
|
|||
*/
|
||||
<R extends Service> ServiceBinding<R> locateServiceBinding(Class<R> serviceRole);
|
||||
|
||||
@Override
|
||||
default void close() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Release resources
|
||||
*/
|
||||
|
|
|
@ -91,7 +91,7 @@ public abstract class AbstractStandardBasicType<T>
|
|||
@Override
|
||||
public String[] getRegistrationKeys() {
|
||||
return registerUnderJavaType()
|
||||
? new String[] { getName(), javaTypeDescriptor.getJavaTypeClass().getName() }
|
||||
? new String[] { getName(), javaTypeDescriptor.getJavaType().getName() }
|
||||
: new String[] { getName() };
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ public abstract class AbstractStandardBasicType<T>
|
|||
|
||||
@Override
|
||||
public final Class getReturnedClass() {
|
||||
return javaTypeDescriptor.getJavaTypeClass();
|
||||
return javaTypeDescriptor.getJavaType();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -169,6 +169,12 @@ public class BasicTypeRegistry implements Serializable {
|
|||
register( new CompositeCustomType( type, keys ) );
|
||||
}
|
||||
|
||||
public void unregister(String... keys) {
|
||||
for ( String key : keys ) {
|
||||
registry.remove( key );
|
||||
}
|
||||
}
|
||||
|
||||
public BasicType getRegisteredType(String key) {
|
||||
return registry.get( key );
|
||||
}
|
||||
|
|
|
@ -16,11 +16,13 @@ import java.util.UUID;
|
|||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.UUIDTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.BasicBinder;
|
||||
import org.hibernate.type.descriptor.sql.BasicExtractor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Specialized type mapping for {@link UUID} and the Postgres UUID data type (which is mapped as OTHER in its
|
||||
|
@ -59,6 +61,12 @@ public class PostgresUUIDType extends AbstractSingleColumnStandardBasicType<UUID
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public BasicJavaDescriptor getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( UUID.class );
|
||||
}
|
||||
|
||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
|
|
|
@ -16,9 +16,14 @@ import org.hibernate.internal.util.compare.EqualsHelper;
|
|||
/**
|
||||
* Abstract adapter for Java type descriptors.
|
||||
*
|
||||
* @apiNote This abstract descriptor implements BasicJavaDescriptor
|
||||
* because we currently only categorize "basic" JavaTypeDescriptors,
|
||||
* as in the {@link javax.persistence.metamodel.Type.PersistenceType#BASIC}
|
||||
* sense
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractTypeDescriptor<T> implements JavaTypeDescriptor<T>, Serializable {
|
||||
public abstract class AbstractTypeDescriptor<T> implements BasicJavaDescriptor<T>, Serializable {
|
||||
private final Class<T> type;
|
||||
private final MutabilityPlan<T> mutabilityPlan;
|
||||
private final Comparator<T> comparator;
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.type.descriptor.java;
|
||||
|
||||
import org.hibernate.type.descriptor.spi.JdbcRecommendedSqlTypeMappingContext;
|
||||
import org.hibernate.type.descriptor.sql.JdbcTypeJavaClassMappings;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @apiNote Currently this is the only high-level categorization of
|
||||
* JavaTypeDescriptor, but 6.0 will have specific JavaTypeDescriptor
|
||||
* categorizations for managed-type, mapped-superclass, identifiable-type, entity, embeddable,
|
||||
* collections.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface BasicJavaDescriptor<T> extends JavaTypeDescriptor<T> {
|
||||
/**
|
||||
* Obtain the "recommended" SQL type descriptor for this Java type. The recommended
|
||||
* aspect comes from the JDBC spec (mostly).
|
||||
*
|
||||
* @param context Contextual information
|
||||
*
|
||||
* @return The recommended SQL type descriptor
|
||||
*/
|
||||
default SqlTypeDescriptor getJdbcRecommendedSqlType(JdbcRecommendedSqlTypeMappingContext context) {
|
||||
// match legacy behavior
|
||||
return context.getTypeConfiguration().getSqlTypeDescriptorRegistry().getDescriptor(
|
||||
JdbcTypeJavaClassMappings.INSTANCE.determineJdbcTypeCodeForJavaClass( getJavaType() )
|
||||
);
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ import org.hibernate.type.descriptor.WrapperOptions;
|
|||
*/
|
||||
public class EnumJavaTypeDescriptor<T extends Enum> extends AbstractTypeDescriptor<T> {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected EnumJavaTypeDescriptor(Class<T> type) {
|
||||
public EnumJavaTypeDescriptor(Class<T> type) {
|
||||
super( type, ImmutableMutabilityPlan.INSTANCE );
|
||||
//JavaTypeDescriptorRegistry.INSTANCE.addDescriptor( this );
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ package org.hibernate.type.descriptor.java;
|
|||
import java.io.Serializable;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.hibernate.internal.util.compare.ComparableComparator;
|
||||
import org.hibernate.internal.util.compare.EqualsHelper;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
||||
/**
|
||||
|
@ -37,17 +39,18 @@ public interface JavaTypeDescriptor<T> extends Serializable {
|
|||
|
||||
/**
|
||||
* Retrieve the mutability plan for this Java type.
|
||||
*
|
||||
* @return The mutability plan
|
||||
*/
|
||||
public MutabilityPlan<T> getMutabilityPlan();
|
||||
@SuppressWarnings("unchecked")
|
||||
default MutabilityPlan<T> getMutabilityPlan() {
|
||||
return ImmutableMutabilityPlan.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the natural comparator for this type.
|
||||
*
|
||||
* @return The natural comparator.
|
||||
*/
|
||||
public Comparator<T> getComparator();
|
||||
default Comparator<T> getComparator() {
|
||||
return Comparable.class.isAssignableFrom( Comparable.class ) ? ComparableComparator.INSTANCE : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a proper hash code for this value.
|
||||
|
@ -56,7 +59,12 @@ public interface JavaTypeDescriptor<T> extends Serializable {
|
|||
*
|
||||
* @return The extracted hash code.
|
||||
*/
|
||||
public int extractHashCode(T value);
|
||||
default int extractHashCode(T value) {
|
||||
if ( value == null ) {
|
||||
throw new IllegalArgumentException( "Value to extract hashCode from cannot be null" );
|
||||
}
|
||||
return value.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if two instances are equal
|
||||
|
@ -66,7 +74,9 @@ public interface JavaTypeDescriptor<T> extends Serializable {
|
|||
*
|
||||
* @return True if the two are considered equal; false otherwise.
|
||||
*/
|
||||
public boolean areEqual(T one, T another);
|
||||
default boolean areEqual(T one, T another) {
|
||||
return EqualsHelper.areEqual( one, another );
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a loggable representation of the value.
|
||||
|
@ -75,11 +85,15 @@ public interface JavaTypeDescriptor<T> extends Serializable {
|
|||
*
|
||||
* @return The loggable representation
|
||||
*/
|
||||
public String extractLoggableRepresentation(T value);
|
||||
default String extractLoggableRepresentation(T value) {
|
||||
return toString( value );
|
||||
}
|
||||
|
||||
public String toString(T value);
|
||||
default String toString(T value) {
|
||||
return value == null ? "null" : value.toString();
|
||||
}
|
||||
|
||||
public T fromString(String string);
|
||||
T fromString(String string);
|
||||
|
||||
/**
|
||||
* Unwrap an instance of our handled Java type into the requested type.
|
||||
|
@ -97,7 +111,7 @@ public interface JavaTypeDescriptor<T> extends Serializable {
|
|||
*
|
||||
* @return The unwrapped value.
|
||||
*/
|
||||
public <X> X unwrap(T value, Class<X> type, WrapperOptions options);
|
||||
<X> X unwrap(T value, Class<X> type, WrapperOptions options);
|
||||
|
||||
/**
|
||||
* Wrap a value as our handled Java type.
|
||||
|
@ -110,5 +124,5 @@ public interface JavaTypeDescriptor<T> extends Serializable {
|
|||
*
|
||||
* @return The wrapped value.
|
||||
*/
|
||||
public <X> T wrap(X value, WrapperOptions options);
|
||||
<X> T wrap(X value, WrapperOptions options);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.type.descriptor.java;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
@ -16,6 +15,7 @@ import org.hibernate.internal.CoreLogging;
|
|||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.spi.RegistryHelper;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
|
@ -84,8 +84,7 @@ public class JavaTypeDescriptorRegistry implements Serializable {
|
|||
}
|
||||
|
||||
private JavaTypeDescriptor addDescriptorInternal(JavaTypeDescriptor descriptor) {
|
||||
JavaTypeDescriptor javaTypeDescriptor = descriptorsByClass.put( descriptor.getJavaType(), descriptor );
|
||||
return javaTypeDescriptor;
|
||||
return descriptorsByClass.put( descriptor.getJavaType(), descriptor );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,43 +112,26 @@ public class JavaTypeDescriptorRegistry implements Serializable {
|
|||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> JavaTypeDescriptor<T> getDescriptor(Class<T> cls) {
|
||||
if ( cls == null ) {
|
||||
throw new IllegalArgumentException( "Class passed to locate Java type descriptor cannot be null" );
|
||||
}
|
||||
public <J> JavaTypeDescriptor<J> getDescriptor(Class<J> cls) {
|
||||
return RegistryHelper.INSTANCE.resolveDescriptor(
|
||||
descriptorsByClass,
|
||||
cls,
|
||||
() -> {
|
||||
if ( Serializable.class.isAssignableFrom( cls ) ) {
|
||||
return new SerializableTypeDescriptor( cls );
|
||||
}
|
||||
|
||||
JavaTypeDescriptor<T> descriptor = descriptorsByClass.get( cls );
|
||||
if ( descriptor != null ) {
|
||||
return descriptor;
|
||||
}
|
||||
log.debugf(
|
||||
"Could not find matching JavaTypeDescriptor for requested Java class [%s]; using fallback. " +
|
||||
"This means Hibernate does not know how to perform certain basic operations in relation to this Java type." +
|
||||
"",
|
||||
cls.getName()
|
||||
);
|
||||
checkEqualsAndHashCode( cls );
|
||||
|
||||
if ( cls.isEnum() ) {
|
||||
descriptor = new EnumJavaTypeDescriptor( cls );
|
||||
descriptorsByClass.put( cls, descriptor );
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
// find the first "assignable" match
|
||||
for ( Map.Entry<Class, JavaTypeDescriptor> entry : descriptorsByClass.entrySet() ) {
|
||||
if ( entry.getKey().isAssignableFrom( cls ) ) {
|
||||
log.debugf( "Using cached JavaTypeDescriptor instance for Java class [%s]", cls.getName() );
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
if ( Serializable.class.isAssignableFrom( cls ) ) {
|
||||
return new SerializableTypeDescriptor( cls );
|
||||
}
|
||||
|
||||
log.debugf(
|
||||
"Could not find matching JavaTypeDescriptor for requested Java class [%s]; using fallback. " +
|
||||
"This means Hibernate does not know how to perform certain basic operations in relation to this Java type." +
|
||||
"",
|
||||
cls.getName()
|
||||
return new FallbackJavaTypeDescriptor<>( cls );
|
||||
}
|
||||
);
|
||||
checkEqualsAndHashCode( cls );
|
||||
|
||||
return new FallbackJavaTypeDescriptor<>( cls );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -29,11 +29,9 @@ public class SerializableTypeDescriptor<T extends Serializable> extends Abstract
|
|||
|
||||
// unfortunately the param types cannot be the same so use something other than 'T' here to make that obvious
|
||||
public static class SerializableMutabilityPlan<S extends Serializable> extends MutableMutabilityPlan<S> {
|
||||
public static final SerializableMutabilityPlan<Serializable> INSTANCE = new SerializableMutabilityPlan<>();
|
||||
|
||||
public static final SerializableMutabilityPlan<Serializable> INSTANCE
|
||||
= new SerializableMutabilityPlan<Serializable>( );
|
||||
|
||||
public SerializableMutabilityPlan() {
|
||||
private SerializableMutabilityPlan() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -124,7 +122,7 @@ public class SerializableTypeDescriptor<T extends Serializable> extends Abstract
|
|||
throw new HibernateException( e );
|
||||
}
|
||||
}
|
||||
else if ( getJavaTypeClass().isInstance( value ) ) {
|
||||
else if ( getJavaType().isInstance( value ) ) {
|
||||
return (T) value;
|
||||
}
|
||||
throw unknownWrap( value.getClass() );
|
||||
|
@ -136,6 +134,6 @@ public class SerializableTypeDescriptor<T extends Serializable> extends Abstract
|
|||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected T fromBytes(byte[] bytes) {
|
||||
return (T) SerializationHelper.deserialize( bytes, getJavaTypeClass().getClassLoader() );
|
||||
return (T) SerializationHelper.deserialize( bytes, getJavaType().getClassLoader() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,13 @@
|
|||
package org.hibernate.type.descriptor.java.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Basically a map from {@link Class} -> {@link JavaTypeDescriptor}
|
||||
*
|
||||
|
@ -19,25 +22,41 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
public class JavaTypeDescriptorRegistry
|
||||
extends org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry
|
||||
implements Serializable {
|
||||
public class JavaTypeDescriptorRegistry implements Serializable {
|
||||
private static final Logger log = Logger.getLogger( JavaTypeDescriptorRegistry.class );
|
||||
|
||||
private final TypeConfiguration typeConfiguration;
|
||||
private final org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry javaTypeDescriptorRegistry;
|
||||
|
||||
private ConcurrentHashMap<Class, JavaTypeDescriptor> descriptorsByClass = new ConcurrentHashMap<>();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public JavaTypeDescriptorRegistry(TypeConfiguration typeConfiguration) {
|
||||
this.typeConfiguration = typeConfiguration;
|
||||
javaTypeDescriptorRegistry = org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JavaTypeDescriptor<T> getDescriptor(Class<T> javaType) {
|
||||
return javaTypeDescriptorRegistry.getDescriptor( javaType );
|
||||
return RegistryHelper.INSTANCE.resolveDescriptor(
|
||||
descriptorsByClass,
|
||||
javaType,
|
||||
() -> {
|
||||
log.debugf(
|
||||
"Could not find matching scoped JavaTypeDescriptor for requested Java class [%s]; " +
|
||||
"falling back to static registry",
|
||||
javaType.getName()
|
||||
);
|
||||
|
||||
return org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry.INSTANCE.getDescriptor( javaType );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDescriptor(JavaTypeDescriptor descriptor) {
|
||||
javaTypeDescriptorRegistry.addDescriptor( descriptor );
|
||||
JavaTypeDescriptor old = descriptorsByClass.put( descriptor.getJavaType(), descriptor );
|
||||
if ( old != null ) {
|
||||
log.debugf(
|
||||
"JavaTypeDescriptorRegistry entry replaced : %s -> %s (was %s)",
|
||||
descriptor.getJavaType(),
|
||||
descriptor,
|
||||
old
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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.type.descriptor.java.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.SerializableTypeDescriptor;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class RegistryHelper {
|
||||
private static final Logger log = Logger.getLogger( RegistryHelper.class );
|
||||
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final RegistryHelper INSTANCE = new RegistryHelper();
|
||||
|
||||
private RegistryHelper() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <J> JavaTypeDescriptor<J> resolveDescriptor(
|
||||
Map<Class,JavaTypeDescriptor> descriptorsByClass,
|
||||
Class<J> cls,
|
||||
Supplier<JavaTypeDescriptor<J>> defaultValueSupplier) {
|
||||
if ( cls == null ) {
|
||||
throw new IllegalArgumentException( "Class passed to locate JavaTypeDescriptor cannot be null" );
|
||||
}
|
||||
|
||||
JavaTypeDescriptor<J> descriptor = descriptorsByClass.get( cls );
|
||||
if ( descriptor != null ) {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
if ( cls.isEnum() ) {
|
||||
descriptor = new EnumJavaTypeDescriptor( cls );
|
||||
descriptorsByClass.put( cls, descriptor );
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
// find the first "assignable" match
|
||||
for ( Map.Entry<Class, JavaTypeDescriptor> entry : descriptorsByClass.entrySet() ) {
|
||||
if ( entry.getKey().isAssignableFrom( cls ) ) {
|
||||
log.debugf( "Using cached JavaTypeDescriptor instance for Java class [%s]", cls.getName() );
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValueSupplier.get();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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.type.descriptor.spi;
|
||||
|
||||
import java.sql.Types;
|
||||
import javax.persistence.EnumType;
|
||||
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* More-or-less a parameter-object intended for use in determining the SQL/JDBC type recommended
|
||||
* by the JDBC spec (explicitly or implicitly) for a given Java type.
|
||||
*
|
||||
* @see org.hibernate.type.descriptor.java.BasicJavaDescriptor#getJdbcRecommendedSqlType
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcRecommendedSqlTypeMappingContext {
|
||||
/**
|
||||
* Was nationalized character datatype requested for the given Java type?
|
||||
*
|
||||
* @return {@code true} if nationalized character datatype should be used; {@code false} otherwise.
|
||||
*/
|
||||
default boolean isNationalized() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Was LOB datatype requested for the given Java type?
|
||||
*
|
||||
* @return {@code true} if LOB datatype should be used; {@code false} otherwise.
|
||||
*/
|
||||
default boolean isLob() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* For enum mappings, what style of storage was requested (name vs. ordinal)?
|
||||
*
|
||||
* @return The enum type.
|
||||
*/
|
||||
default EnumType getEnumeratedType() {
|
||||
return EnumType.ORDINAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* When mapping a boolean type to the database what is the preferred SQL type code to use?
|
||||
* <p/>
|
||||
* Specifically names the key into the
|
||||
* {@link org.hibernate.type.descriptor.sql.spi.SqlTypeDescriptorRegistry}.
|
||||
*/
|
||||
default int getPreferredSqlTypeCodeForBoolean() {
|
||||
return Types.BOOLEAN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to the TypeConfiguration for access to various type-system registries.
|
||||
*/
|
||||
TypeConfiguration getTypeConfiguration();
|
||||
}
|
|
@ -10,7 +10,9 @@ import java.io.Serializable;
|
|||
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Descriptor for the <tt>SQL</tt>/<tt>JDBC</tt> side of a value mapping.
|
||||
|
@ -38,6 +40,15 @@ public interface SqlTypeDescriptor extends Serializable {
|
|||
*/
|
||||
boolean canBeRemapped();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
// match legacy behavior
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor(
|
||||
JdbcTypeJavaClassMappings.INSTANCE.determineJavaClassForJdbcTypeCode( getSqlType() )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the binder (setting JDBC in-going parameter values) capable of handling values of the type described by the
|
||||
* passed descriptor.
|
||||
|
|
|
@ -151,7 +151,7 @@ public class SqlTypeDescriptorRegistry implements Serializable {
|
|||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaTypeClass() ) ) {
|
||||
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaType() ) ) {
|
||||
return VarbinaryTypeDescriptor.INSTANCE.getBinder( javaTypeDescriptor );
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,7 @@ public class SqlTypeDescriptorRegistry implements Serializable {
|
|||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ValueExtractor getExtractor(JavaTypeDescriptor javaTypeDescriptor) {
|
||||
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaTypeClass() ) ) {
|
||||
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaType() ) ) {
|
||||
return VarbinaryTypeDescriptor.INSTANCE.getExtractor( javaTypeDescriptor );
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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.test.converter.custom;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.boot.spi.MetadataBuilderImplementor;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.tool.schema.Action;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CustomTypeConverterTest extends BaseUnitTestCase {
|
||||
@Test
|
||||
public void testConverterAppliedStaticRegistration() {
|
||||
// this is how we told users to do it previously using the static reference -
|
||||
// make sure it still works for now
|
||||
org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry.INSTANCE.addDescriptor( MyCustomJavaTypeDescriptor.INSTANCE );
|
||||
org.hibernate.type.descriptor.sql.SqlTypeDescriptorRegistry.INSTANCE.addDescriptor( MyCustomSqlTypeDescriptor.INSTANCE );
|
||||
|
||||
try ( final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )
|
||||
.build() ) {
|
||||
final MetadataSources metadataSources = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( MyCustomConverter.class )
|
||||
.addAnnotatedClass( MyEntity.class );
|
||||
final MetadataBuilderImplementor metadataBuilder = (MetadataBuilderImplementor) metadataSources.getMetadataBuilder();
|
||||
|
||||
final TypeConfiguration bootTypeConfiguration = metadataBuilder.getBootstrapContext().getTypeConfiguration();
|
||||
performAssertions( metadataBuilder, bootTypeConfiguration );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConverterAppliedScopedRegistration() {
|
||||
|
||||
try ( final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )
|
||||
.build() ) {
|
||||
final MetadataSources metadataSources = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( MyCustomConverter.class )
|
||||
.addAnnotatedClass( MyEntity.class );
|
||||
final MetadataBuilderImplementor metadataBuilder = (MetadataBuilderImplementor) metadataSources.getMetadataBuilder();
|
||||
|
||||
// now the new scoped way
|
||||
final TypeConfiguration bootTypeConfiguration = metadataBuilder.getBootstrapContext().getTypeConfiguration();
|
||||
bootTypeConfiguration.getJavaTypeDescriptorRegistry()
|
||||
.addDescriptor( MyCustomJavaTypeDescriptor.INSTANCE );
|
||||
bootTypeConfiguration.getSqlTypeDescriptorRegistry()
|
||||
.addDescriptor( MyCustomSqlTypeDescriptor.INSTANCE );
|
||||
|
||||
performAssertions( metadataBuilder, bootTypeConfiguration );
|
||||
}
|
||||
}
|
||||
|
||||
protected void performAssertions(
|
||||
MetadataBuilderImplementor metadataBuilder,
|
||||
TypeConfiguration bootTypeConfiguration) {
|
||||
try ( final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) metadataBuilder.build().buildSessionFactory()) {
|
||||
assertThat(
|
||||
sessionFactory.getMetamodel().getTypeConfiguration(),
|
||||
sameInstance( bootTypeConfiguration )
|
||||
);
|
||||
|
||||
assertThat(
|
||||
bootTypeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( MyCustomJavaType.class ),
|
||||
sameInstance( MyCustomJavaTypeDescriptor.INSTANCE )
|
||||
);
|
||||
|
||||
assertThat(
|
||||
bootTypeConfiguration.getSqlTypeDescriptorRegistry().getDescriptor( MyCustomSqlTypeDescriptor.INSTANCE.getSqlType() ),
|
||||
sameInstance( MyCustomSqlTypeDescriptor.INSTANCE )
|
||||
);
|
||||
|
||||
final EntityPersister entityPersister = sessionFactory.getMetamodel().entityPersister( MyEntity.class );
|
||||
entityPersister.getPropertyType( "customType" );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.test.converter.custom;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Converter;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Converter( autoApply = true )
|
||||
public class MyCustomConverter implements AttributeConverter<MyCustomJavaType, String> {
|
||||
@Override
|
||||
public String convertToDatabaseColumn(MyCustomJavaType attribute) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MyCustomJavaType convertToEntityAttribute(String dbData) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.test.converter.custom;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class MyCustomJavaType implements Comparable<MyCustomJavaType> {
|
||||
private String payload;
|
||||
|
||||
public MyCustomJavaType() {
|
||||
this( null );
|
||||
}
|
||||
|
||||
public MyCustomJavaType(String payload) {
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public String getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
public void setPayload(String payload) {
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(MyCustomJavaType other) {
|
||||
if ( getPayload() == null ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( other == null || other.getPayload() == null ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return getPayload().compareTo( other.getPayload() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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.test.converter.custom;
|
||||
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.MutableMutabilityPlan;
|
||||
import org.hibernate.type.descriptor.spi.JdbcRecommendedSqlTypeMappingContext;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class MyCustomJavaTypeDescriptor implements BasicJavaDescriptor<MyCustomJavaType> {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final MyCustomJavaTypeDescriptor INSTANCE = new MyCustomJavaTypeDescriptor();
|
||||
|
||||
private final MutableMutabilityPlan<MyCustomJavaType> mutabilityPlan = new MutableMutabilityPlan<MyCustomJavaType>() {
|
||||
@Override
|
||||
protected MyCustomJavaType deepCopyNotNull(MyCustomJavaType value) {
|
||||
return value == null ? null : new MyCustomJavaType( value.getPayload() );
|
||||
}
|
||||
};
|
||||
|
||||
private MyCustomJavaTypeDescriptor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getJavaTypeClass() {
|
||||
return MyCustomJavaType.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlTypeDescriptor getJdbcRecommendedSqlType(JdbcRecommendedSqlTypeMappingContext context) {
|
||||
return MyCustomSqlTypeDescriptor.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutabilityPlan getMutabilityPlan() {
|
||||
return mutabilityPlan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MyCustomJavaType fromString(String string) {
|
||||
return StringHelper.isEmpty( string ) ? null : new MyCustomJavaType( string );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MyCustomJavaType wrap(Object value, WrapperOptions options) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
else if ( String.class.isInstance( value ) ) {
|
||||
return new MyCustomJavaType( (String) value );
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException( "Wrapping value as MyCustomJavaType only supported for String or MyCustomJdbcType : " + value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unwrap(MyCustomJavaType value, Class type, WrapperOptions options) {
|
||||
if ( String.class.isAssignableFrom( type ) ) {
|
||||
return value.getPayload();
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException( "Unwrapping MyCustomJavaType value only supported for String or MyCustomJdbcType : " + value );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.test.converter.custom;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.BasicBinder;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
|
||||
|
||||
/**
|
||||
* A custom SqlTypeDescriptor. For example, this might be used to provide support
|
||||
* for a "non-standard" SQL type or to provide some special handling of values (e.g.
|
||||
* Oracle's dodgy handling of `""` as `null` but only in certain uses).
|
||||
*
|
||||
* This descriptor shows an example of replacing how VARCHAR values are handled.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class MyCustomSqlTypeDescriptor implements SqlTypeDescriptor {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final MyCustomSqlTypeDescriptor INSTANCE = new MyCustomSqlTypeDescriptor();
|
||||
|
||||
private MyCustomSqlTypeDescriptor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSqlType() {
|
||||
// given the Oracle example above we might want to replace the
|
||||
// handling of VARCHAR
|
||||
return Types.VARCHAR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeRemapped() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
|
||||
final String valueStr = javaTypeDescriptor.unwrap( value, String.class, options );
|
||||
if ( valueStr == null || valueStr.trim().isEmpty() ) {
|
||||
st.setNull( index, getSqlType() );
|
||||
}
|
||||
else {
|
||||
st.setString( index, valueStr );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options) throws SQLException {
|
||||
final String valueStr = javaTypeDescriptor.unwrap( value, String.class, options );
|
||||
if ( valueStr == null || valueStr.trim().isEmpty() ) {
|
||||
st.setNull( name, getSqlType() );
|
||||
}
|
||||
else {
|
||||
st.setString( name, valueStr );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return VarcharTypeDescriptor.INSTANCE.getExtractor( javaTypeDescriptor );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.test.converter.custom;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
@Table( name = "CUST_TYPE_CONV_ENTITY")
|
||||
public class MyEntity {
|
||||
private Integer id;
|
||||
private MyCustomJavaType customType;
|
||||
|
||||
public MyEntity() {
|
||||
}
|
||||
|
||||
public MyEntity(Integer id, MyCustomJavaType customType) {
|
||||
this.id = id;
|
||||
this.customType = customType;
|
||||
}
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
// NOTE : this AttributeConverter should be auto-applied here
|
||||
|
||||
@Basic
|
||||
public MyCustomJavaType getCustomType() {
|
||||
return customType;
|
||||
}
|
||||
|
||||
public void setCustomType(MyCustomJavaType customType) {
|
||||
this.customType = customType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test illustrating use of an AttributeConverter over custom
|
||||
* java / sql type descriptors
|
||||
*/
|
||||
package org.hibernate.test.converter.custom;
|
|
@ -83,7 +83,7 @@ public class Java8DateTimeTests extends BaseNonConfigCoreFunctionalTestCase {
|
|||
String.format(
|
||||
"%s (%s) -> %s",
|
||||
propertyBinding.getName(),
|
||||
javaTypeDescriptor.getJavaTypeClass().getSimpleName(),
|
||||
javaTypeDescriptor.getJavaType().getSimpleName(),
|
||||
javaTypeDescriptor.toString( propertyBinding.getGetter( TheEntity.class ).get( theEntity ) )
|
||||
)
|
||||
);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import org.apache.tools.ant.filters.ReplaceTokens
|
||||
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
|
@ -8,13 +10,27 @@
|
|||
apply from: rootProject.file( 'gradle/published-java-module.gradle' )
|
||||
apply plugin: 'hibernate-matrix-testing'
|
||||
|
||||
ext {
|
||||
db = project.hasProperty('db') ? project.getProperty('db') : 'h2'
|
||||
dbBundle = [
|
||||
h2 : [
|
||||
'db.dialect' : 'org.hibernate.spatial.dialect.h2geodb.GeoDBDialect',
|
||||
'jdbc.driver': 'org.h2.Driver',
|
||||
'jdbc.user' : 'sa',
|
||||
'jdbc.pass' : '',
|
||||
'jdbc.url' : 'jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;LOCK_TIMEOUT=10000',
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
description = 'Integrate support for Spatial/GIS data into Hibernate O/RM'
|
||||
|
||||
dependencies {
|
||||
compile(project(':hibernate-core'))
|
||||
compile( project(':hibernate-core') )
|
||||
compile( libraries.geolatte )
|
||||
|
||||
compile( 'org.postgresql:postgresql:42.1.4' )
|
||||
|
||||
compile('org.postgresql:postgresql:42.1.4')
|
||||
compile([group: 'org.geolatte', name: 'geolatte-geom', version: '1.3.0'])
|
||||
compile(libraries.dom4j) {
|
||||
transitive = false
|
||||
}
|
||||
|
@ -40,3 +56,25 @@ sourceSets.test.resources {
|
|||
setSrcDirs(['src/test/java', 'src/test/resources'])
|
||||
}
|
||||
|
||||
processTestResources {
|
||||
doLast {
|
||||
copy {
|
||||
from( sourceSets.test.java.srcDirs ) {
|
||||
include '**/*.properties'
|
||||
include '**/*.xml'
|
||||
}
|
||||
into sourceSets.test.java.outputDir
|
||||
}
|
||||
copy {
|
||||
from file( 'src/test/resources' )
|
||||
into file( "${buildDir}/resources/test" )
|
||||
exclude 'src/test/resources/arquillian.xml'
|
||||
exclude 'src/test/resources/hibernate.properties'
|
||||
}
|
||||
copy {
|
||||
from file( 'src/test/resources/hibernate.properties' )
|
||||
into file( "${buildDir}/resources/test" )
|
||||
filter( ReplaceTokens, tokens: dbBundle[db] )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,12 @@
|
|||
|
||||
package org.hibernate.spatial;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.descriptor.spi.JdbcRecommendedSqlTypeMappingContext;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
import org.geolatte.geom.Geometry;
|
||||
import org.geolatte.geom.codec.Wkt;
|
||||
|
@ -35,6 +38,11 @@ public class GeolatteGeometryJavaTypeDescriptor extends AbstractTypeDescriptor<G
|
|||
super( Geometry.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlTypeDescriptor getJdbcRecommendedSqlType(JdbcRecommendedSqlTypeMappingContext context) {
|
||||
return context.getTypeConfiguration().getSqlTypeDescriptorRegistry().getDescriptor( Types.ARRAY );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(Geometry value) {
|
||||
return value.toString();
|
||||
|
|
|
@ -27,6 +27,18 @@ import org.geolatte.geom.Polygon;
|
|||
*/
|
||||
public class GeolatteGeometryType extends AbstractSingleColumnStandardBasicType<Geometry> implements Spatial {
|
||||
|
||||
public static final String[] REG_KEYS = {
|
||||
Geometry.class.getCanonicalName(),
|
||||
Point.class.getCanonicalName(),
|
||||
Polygon.class.getCanonicalName(),
|
||||
MultiPolygon.class.getCanonicalName(),
|
||||
LineString.class.getCanonicalName(),
|
||||
MultiLineString.class.getCanonicalName(),
|
||||
MultiPoint.class.getCanonicalName(),
|
||||
GeometryCollection.class.getCanonicalName(),
|
||||
"geolatte_geometry"
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs an instance with the specified {@code SqlTypeDescriptor}
|
||||
*
|
||||
|
@ -38,17 +50,7 @@ public class GeolatteGeometryType extends AbstractSingleColumnStandardBasicType<
|
|||
|
||||
@Override
|
||||
public String[] getRegistrationKeys() {
|
||||
return new String[] {
|
||||
Geometry.class.getCanonicalName(),
|
||||
Point.class.getCanonicalName(),
|
||||
Polygon.class.getCanonicalName(),
|
||||
MultiPolygon.class.getCanonicalName(),
|
||||
LineString.class.getCanonicalName(),
|
||||
MultiLineString.class.getCanonicalName(),
|
||||
MultiPoint.class.getCanonicalName(),
|
||||
GeometryCollection.class.getCanonicalName(),
|
||||
"geolatte_geometry"
|
||||
};
|
||||
return REG_KEYS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.testing.converter;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Converter;
|
||||
|
||||
import org.hibernate.spatial.dialect.h2geodb.GeoDbWkb;
|
||||
|
||||
import org.geolatte.geom.Geometry;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Converter( autoApply = true )
|
||||
public class GeometryConverter implements AttributeConverter<Geometry,byte[]> {
|
||||
@Override
|
||||
public byte[] convertToDatabaseColumn(Geometry attribute) {
|
||||
if ( attribute == null ) {
|
||||
return null;
|
||||
}
|
||||
return GeoDbWkb.to( attribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Geometry convertToEntityAttribute(byte[] dbData) {
|
||||
if ( dbData == null ) {
|
||||
return null;
|
||||
}
|
||||
return GeoDbWkb.from( dbData );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.testing.converter;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.boot.spi.MetadataBuilderImplementor;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.spatial.GeolatteGeometryJavaTypeDescriptor;
|
||||
import org.hibernate.spatial.dialect.h2geodb.GeoDBDialect;
|
||||
import org.hibernate.tool.schema.Action;
|
||||
import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.geolatte.geom.Geometry;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class GeometryConverterTest extends BaseUnitTestCase {
|
||||
|
||||
@Test
|
||||
public void testConverterUsage() {
|
||||
try ( final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.DIALECT, GeoDBDialect.class )
|
||||
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )
|
||||
.build() ) {
|
||||
final MetadataSources metadataSources = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( GeometryConverter.class )
|
||||
.addAnnotatedClass( MyEntity.class );
|
||||
final MetadataBuilderImplementor metadataBuilder = (MetadataBuilderImplementor) metadataSources.getMetadataBuilder();
|
||||
|
||||
try ( final SessionFactoryImplementor sessionFactory =
|
||||
(SessionFactoryImplementor) metadataBuilder.build().buildSessionFactory() ) {
|
||||
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getMetamodel().getTypeConfiguration();
|
||||
|
||||
assertThat(
|
||||
typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Geometry.class ),
|
||||
sameInstance( GeolatteGeometryJavaTypeDescriptor.INSTANCE )
|
||||
);
|
||||
|
||||
// todo (5.3) : what to assert wrt to SqlTypeDescriptor? Anything?
|
||||
|
||||
final EntityPersister entityPersister = sessionFactory.getMetamodel().entityPersister( MyEntity.class );
|
||||
final AttributeConverterTypeAdapter geometryAttributeType = assertTyping(
|
||||
AttributeConverterTypeAdapter.class,
|
||||
entityPersister.getPropertyType( "geometry" )
|
||||
);
|
||||
|
||||
final JpaAttributeConverter converter = assertTyping(
|
||||
JpaAttributeConverter.class,
|
||||
geometryAttributeType.getAttributeConverter()
|
||||
);
|
||||
|
||||
assert GeometryConverter.class.equals( converter.getConverterBean().getBeanClass() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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.testing.converter;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.geolatte.geom.Geometry;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
@Table( name = "SP_CUST_TYPE_CONV_ENTITY")
|
||||
public class MyEntity {
|
||||
private Integer id;
|
||||
private Geometry geometry;
|
||||
|
||||
public MyEntity() {
|
||||
}
|
||||
|
||||
public MyEntity(Integer id, Geometry geometry) {
|
||||
this.id = id;
|
||||
this.geometry = geometry;
|
||||
}
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
// NOTE : the AttributeConverter should be auto-applied here
|
||||
|
||||
@Basic
|
||||
public Geometry getGeometry() {
|
||||
return geometry;
|
||||
}
|
||||
|
||||
public void setGeometry(Geometry geometry) {
|
||||
this.geometry = geometry;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Make sure that JPA {@link javax.persistence.AttributeConverter}
|
||||
* implementations using Geolatte types work with hibernate-spatial
|
||||
*/
|
||||
package org.hibernate.spatial.testing.converter;
|
Loading…
Reference in New Issue