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'
|
javassistVersion = '3.22.0-GA'
|
||||||
byteBuddyVersion = '1.8.0' // Now with JDK10 compatibility and preliminary support for JDK11
|
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
|
// Wildfly version targeted by module ZIP; Arquillian/Shrinkwrap versions used for CDI testing and testing the module ZIP
|
||||||
wildflyVersion = '12.0.0.Final'
|
wildflyVersion = '12.0.0.Final'
|
||||||
arquillianVersion = '1.1.11.Final'
|
arquillianVersion = '1.1.11.Final'
|
||||||
|
@ -31,6 +33,8 @@ ext {
|
||||||
shrinkwrapDescriptorsVersion = '2.0.0-alpha-8'
|
shrinkwrapDescriptorsVersion = '2.0.0-alpha-8'
|
||||||
wildflyArquillianContainerVersion = '2.0.0.Final'
|
wildflyArquillianContainerVersion = '2.0.0.Final'
|
||||||
|
|
||||||
|
jodaTimeVersion = '2.3'
|
||||||
|
|
||||||
libraries = [
|
libraries = [
|
||||||
// Ant
|
// Ant
|
||||||
ant: 'org.apache.ant:ant:1.8.2',
|
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: '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',
|
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
|
// Animal Sniffer Ant Task and Java 1.6 API signature file
|
||||||
// not using 1.9 for the time being due to MANIMALSNIFFER-34
|
// not using 1.9 for the time being due to MANIMALSNIFFER-34
|
||||||
animal_sniffer: 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.13',
|
animal_sniffer: 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.13',
|
||||||
|
@ -105,6 +111,8 @@ ext {
|
||||||
db2: 'com.ibm.db2:db2jcc:10.5',
|
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
|
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',
|
informix: 'com.ibm.informix:jdbc:4.10.7.20160517',
|
||||||
jboss_jta: "org.jboss.jbossts:jbossjta:4.16.4.Final",
|
jboss_jta: "org.jboss.jbossts:jbossjta:4.16.4.Final",
|
||||||
xapool: "com.experlog:xapool:1.5.0",
|
xapool: "com.experlog:xapool:1.5.0",
|
||||||
|
|
|
@ -69,7 +69,7 @@ dependencies {
|
||||||
testCompile( libraries.classmate )
|
testCompile( libraries.classmate )
|
||||||
testCompile( libraries.mockito )
|
testCompile( libraries.mockito )
|
||||||
testCompile( libraries.mockito_inline )
|
testCompile( libraries.mockito_inline )
|
||||||
testCompile( 'joda-time:joda-time:2.3' )
|
testCompile( libraries.jodaTime )
|
||||||
|
|
||||||
testCompile( libraries.cdi ) {
|
testCompile( libraries.cdi ) {
|
||||||
// we need to force it to make sure we influence the one coming from arquillian
|
// we need to force it to make sure we influence the one coming from arquillian
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
package org.hibernate.boot.model;
|
package org.hibernate.boot.model;
|
||||||
|
|
||||||
import org.hibernate.type.BasicType;
|
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.sql.SqlTypeDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
@ -19,34 +21,56 @@ import org.hibernate.usertype.UserType;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface TypeContributions {
|
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);
|
void contributeType(BasicType type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 5.3) It will be replaced by {@link #contributeType(BasicType)}
|
* @deprecated (since 5.3) Use {@link #contributeType(BasicType)} instead. Basic
|
||||||
* but do not move to it before 6.0
|
* 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
|
@Deprecated
|
||||||
void contributeType(BasicType type, String... keys);
|
void contributeType(BasicType type, String... keys);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 5.3) It will be replaced by {@link #contributeType(BasicType)}
|
* @deprecated (since 5.3) Use {@link #contributeType(BasicType)} instead.
|
||||||
* but do not move to it before 6.0
|
* {@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);
|
void contributeType(UserType type, String... keys);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 5.3) It will be replaced by {@link #contributeType(BasicType)}
|
* @deprecated (since 5.3) Use {@link #contributeType(BasicType)} instead.
|
||||||
* but do not move to it before 6.0
|
* {@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);
|
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;
|
package org.hibernate.boot.model.convert.spi;
|
||||||
|
|
||||||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
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
|
* Access to information that implementors of
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class StandardServiceRegistryBuilder {
|
||||||
* @param bootstrapServiceRegistry Provided bootstrap registry to use.
|
* @param bootstrapServiceRegistry Provided bootstrap registry to use.
|
||||||
*/
|
*/
|
||||||
public StandardServiceRegistryBuilder(BootstrapServiceRegistry bootstrapServiceRegistry) {
|
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.
|
* @param bootstrapServiceRegistry Provided bootstrap registry to use.
|
||||||
*/
|
*/
|
||||||
public StandardServiceRegistryBuilder(BootstrapServiceRegistry bootstrapServiceRegistry, LoadedConfig loadedConfigBaseline) {
|
public StandardServiceRegistryBuilder(
|
||||||
|
BootstrapServiceRegistry bootstrapServiceRegistry,
|
||||||
|
LoadedConfig loadedConfigBaseline) {
|
||||||
this.settings = Environment.getProperties();
|
this.settings = Environment.getProperties();
|
||||||
this.bootstrapServiceRegistry = bootstrapServiceRegistry;
|
this.bootstrapServiceRegistry = bootstrapServiceRegistry;
|
||||||
this.configLoader = new ConfigLoader( 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.
|
* 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
|
* 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.
|
* {@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()
|
||||||
* @see #configure(String)
|
* @see #configure(String)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( {"unchecked"})
|
@SuppressWarnings({"unchecked"})
|
||||||
public StandardServiceRegistryBuilder loadProperties(String resourceName) {
|
public StandardServiceRegistryBuilder loadProperties(String resourceName) {
|
||||||
settings.putAll( configLoader.loadProperties( resourceName ) );
|
settings.putAll( configLoader.loadProperties( resourceName ) );
|
||||||
return this;
|
return this;
|
||||||
|
@ -122,7 +124,7 @@ public class StandardServiceRegistryBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read settings from a {@link java.util.Properties} file by File reference
|
* 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
|
* 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.
|
* {@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()
|
||||||
* @see #configure(String)
|
* @see #configure(String)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( {"unchecked"})
|
@SuppressWarnings({"unchecked"})
|
||||||
public StandardServiceRegistryBuilder loadProperties(File file) {
|
public StandardServiceRegistryBuilder loadProperties(File file) {
|
||||||
settings.putAll( configLoader.loadProperties( file ) );
|
settings.putAll( configLoader.loadProperties( file ) );
|
||||||
return this;
|
return this;
|
||||||
|
@ -171,7 +173,7 @@ public class StandardServiceRegistryBuilder {
|
||||||
return configure( configLoader.loadConfigXmlUrl( url ) );
|
return configure( configLoader.loadConfigXmlUrl( url ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings( {"unchecked"})
|
@SuppressWarnings({"unchecked"})
|
||||||
public StandardServiceRegistryBuilder configure(LoadedConfig loadedConfig) {
|
public StandardServiceRegistryBuilder configure(LoadedConfig loadedConfig) {
|
||||||
aggregatedCfgXml.merge( loadedConfig );
|
aggregatedCfgXml.merge( loadedConfig );
|
||||||
settings.putAll( loadedConfig.getConfigurationValues() );
|
settings.putAll( loadedConfig.getConfigurationValues() );
|
||||||
|
@ -187,7 +189,7 @@ public class StandardServiceRegistryBuilder {
|
||||||
*
|
*
|
||||||
* @return this, for method chaining
|
* @return this, for method chaining
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( {"unchecked", "UnusedDeclaration"})
|
@SuppressWarnings({"unchecked", "UnusedDeclaration"})
|
||||||
public StandardServiceRegistryBuilder applySetting(String settingName, Object value) {
|
public StandardServiceRegistryBuilder applySetting(String settingName, Object value) {
|
||||||
settings.put( settingName, value );
|
settings.put( settingName, value );
|
||||||
return this;
|
return this;
|
||||||
|
@ -200,7 +202,7 @@ public class StandardServiceRegistryBuilder {
|
||||||
*
|
*
|
||||||
* @return this, for method chaining
|
* @return this, for method chaining
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( {"unchecked", "UnusedDeclaration"})
|
@SuppressWarnings({"unchecked", "UnusedDeclaration"})
|
||||||
public StandardServiceRegistryBuilder applySettings(Map settings) {
|
public StandardServiceRegistryBuilder applySettings(Map settings) {
|
||||||
this.settings.putAll( settings );
|
this.settings.putAll( settings );
|
||||||
return this;
|
return this;
|
||||||
|
@ -213,7 +215,7 @@ public class StandardServiceRegistryBuilder {
|
||||||
*
|
*
|
||||||
* @return this, for method chaining
|
* @return this, for method chaining
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( {"UnusedDeclaration"})
|
@SuppressWarnings({"UnusedDeclaration"})
|
||||||
public StandardServiceRegistryBuilder addInitiator(StandardServiceInitiator initiator) {
|
public StandardServiceRegistryBuilder addInitiator(StandardServiceInitiator initiator) {
|
||||||
initiators.add( initiator );
|
initiators.add( initiator );
|
||||||
return this;
|
return this;
|
||||||
|
@ -227,7 +229,7 @@ public class StandardServiceRegistryBuilder {
|
||||||
*
|
*
|
||||||
* @return this, for method chaining
|
* @return this, for method chaining
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( {"unchecked"})
|
@SuppressWarnings({"unchecked"})
|
||||||
public StandardServiceRegistryBuilder addService(final Class serviceRole, final Service service) {
|
public StandardServiceRegistryBuilder addService(final Class serviceRole, final Service service) {
|
||||||
providedServices.add( new ProvidedService( serviceRole, service ) );
|
providedServices.add( new ProvidedService( serviceRole, service ) );
|
||||||
return this;
|
return this;
|
||||||
|
@ -289,9 +291,11 @@ public class StandardServiceRegistryBuilder {
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
private void applyServiceContributingIntegrators() {
|
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 ) ) {
|
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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,13 +50,13 @@ import org.hibernate.type.Type;
|
||||||
import org.hibernate.type.descriptor.JdbcTypeNameMapper;
|
import org.hibernate.type.descriptor.JdbcTypeNameMapper;
|
||||||
import org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter;
|
import org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter;
|
||||||
import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter;
|
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.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.JdbcTypeJavaClassMappings;
|
||||||
import org.hibernate.type.descriptor.sql.LobTypeMappings;
|
import org.hibernate.type.descriptor.sql.LobTypeMappings;
|
||||||
import org.hibernate.type.descriptor.sql.NationalizedTypeMappings;
|
import org.hibernate.type.descriptor.sql.NationalizedTypeMappings;
|
||||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorRegistry;
|
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
import org.hibernate.usertype.DynamicParameterizedType;
|
import org.hibernate.usertype.DynamicParameterizedType;
|
||||||
|
|
||||||
|
@ -576,13 +576,13 @@ public class SimpleValue implements KeyValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaTypeDescriptorRegistry getJavaTypeDescriptorRegistry() {
|
public org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry getJavaTypeDescriptorRegistry() {
|
||||||
return metadata.getTypeConfiguration().getJavaTypeDescriptorRegistry();
|
return metadata.getTypeConfiguration().getJavaTypeDescriptorRegistry();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
final JavaTypeDescriptor entityAttributeJavaTypeDescriptor = jpaAttributeConverter.getDomainJavaTypeDescriptor();
|
final BasicJavaDescriptor entityAttributeJavaTypeDescriptor = jpaAttributeConverter.getDomainJavaTypeDescriptor();
|
||||||
|
|
||||||
|
|
||||||
// build the SqlTypeDescriptor adapter ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// 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
|
// 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
|
// of ResultSets). See JdbcTypeJavaClassMappings for details. Again, given example, this should return
|
||||||
// VARCHAR/CHAR
|
// 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 ( isLob() ) {
|
||||||
if ( LobTypeMappings.INSTANCE.hasCorrespondingLobCode( jdbcTypeCode ) ) {
|
if ( LobTypeMappings.INSTANCE.hasCorrespondingLobCode( jdbcTypeCode ) ) {
|
||||||
jdbcTypeCode = LobTypeMappings.INSTANCE.getCorrespondingLobCode( 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.metamodel.model.convert.spi.JpaAttributeConverter;
|
||||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
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> {
|
public class JpaAttributeConverterImpl<O,R> implements JpaAttributeConverter<O,R> {
|
||||||
private final ManagedBean<AttributeConverter<O,R>> attributeConverterBean;
|
private final ManagedBean<AttributeConverter<O,R>> attributeConverterBean;
|
||||||
private final JavaTypeDescriptor<AttributeConverter<O, R>> converterJavaTypeDescriptor;
|
private final JavaTypeDescriptor<AttributeConverter<O, R>> converterJavaTypeDescriptor;
|
||||||
private final JavaTypeDescriptor<O> domainJavaTypeDescriptor;
|
private final BasicJavaDescriptor<O> domainJavaTypeDescriptor;
|
||||||
private final JavaTypeDescriptor<R> relationalJavaTypeDescriptor;
|
private final BasicJavaDescriptor<R> relationalJavaTypeDescriptor;
|
||||||
|
|
||||||
public JpaAttributeConverterImpl(
|
public JpaAttributeConverterImpl(
|
||||||
ManagedBean<AttributeConverter<O, R>> attributeConverterBean,
|
ManagedBean<AttributeConverter<O, R>> attributeConverterBean,
|
||||||
|
@ -30,8 +31,13 @@ public class JpaAttributeConverterImpl<O,R> implements JpaAttributeConverter<O,R
|
||||||
JavaTypeDescriptor<R> relationalJavaTypeDescriptor) {
|
JavaTypeDescriptor<R> relationalJavaTypeDescriptor) {
|
||||||
this.attributeConverterBean = attributeConverterBean;
|
this.attributeConverterBean = attributeConverterBean;
|
||||||
this.converterJavaTypeDescriptor = converterJavaTypeDescriptor;
|
this.converterJavaTypeDescriptor = converterJavaTypeDescriptor;
|
||||||
this.domainJavaTypeDescriptor = domainJavaTypeDescriptor;
|
this.domainJavaTypeDescriptor = (BasicJavaDescriptor<O>) domainJavaTypeDescriptor;
|
||||||
this.relationalJavaTypeDescriptor = relationalJavaTypeDescriptor;
|
this.relationalJavaTypeDescriptor = (BasicJavaDescriptor<R>) relationalJavaTypeDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ManagedBean<AttributeConverter<O, R>> getConverterBean() {
|
||||||
|
return attributeConverterBean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,12 +56,12 @@ public class JpaAttributeConverterImpl<O,R> implements JpaAttributeConverter<O,R
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaTypeDescriptor<O> getDomainJavaTypeDescriptor() {
|
public BasicJavaDescriptor<O> getDomainJavaTypeDescriptor() {
|
||||||
return domainJavaTypeDescriptor;
|
return domainJavaTypeDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaTypeDescriptor<R> getRelationalJavaTypeDescriptor() {
|
public BasicJavaDescriptor<R> getRelationalJavaTypeDescriptor() {
|
||||||
return relationalJavaTypeDescriptor;
|
return relationalJavaTypeDescriptor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ package org.hibernate.metamodel.model.convert.spi;
|
||||||
|
|
||||||
import javax.persistence.AttributeConverter;
|
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;
|
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> {
|
public interface JpaAttributeConverter<O,R> extends BasicValueConverter<O,R> {
|
||||||
JavaTypeDescriptor<AttributeConverter<O,R>> getConverterJavaTypeDescriptor();
|
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
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface ServiceRegistry {
|
public interface ServiceRegistry extends AutoCloseable {
|
||||||
/**
|
/**
|
||||||
* Retrieve this registry's parent registry.
|
* Retrieve this registry's parent registry.
|
||||||
*
|
*
|
||||||
|
@ -56,4 +56,6 @@ public interface ServiceRegistry {
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,11 @@ public interface ServiceRegistryImplementor extends ServiceRegistry {
|
||||||
*/
|
*/
|
||||||
<R extends Service> ServiceBinding<R> locateServiceBinding(Class<R> serviceRole);
|
<R extends Service> ServiceBinding<R> locateServiceBinding(Class<R> serviceRole);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void close() {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Release resources
|
* Release resources
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -91,7 +91,7 @@ public abstract class AbstractStandardBasicType<T>
|
||||||
@Override
|
@Override
|
||||||
public String[] getRegistrationKeys() {
|
public String[] getRegistrationKeys() {
|
||||||
return registerUnderJavaType()
|
return registerUnderJavaType()
|
||||||
? new String[] { getName(), javaTypeDescriptor.getJavaTypeClass().getName() }
|
? new String[] { getName(), javaTypeDescriptor.getJavaType().getName() }
|
||||||
: new String[] { getName() };
|
: new String[] { getName() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ public abstract class AbstractStandardBasicType<T>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Class getReturnedClass() {
|
public final Class getReturnedClass() {
|
||||||
return javaTypeDescriptor.getJavaTypeClass();
|
return javaTypeDescriptor.getJavaType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -169,6 +169,12 @@ public class BasicTypeRegistry implements Serializable {
|
||||||
register( new CompositeCustomType( type, keys ) );
|
register( new CompositeCustomType( type, keys ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void unregister(String... keys) {
|
||||||
|
for ( String key : keys ) {
|
||||||
|
registry.remove( key );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public BasicType getRegisteredType(String key) {
|
public BasicType getRegisteredType(String key) {
|
||||||
return registry.get( key );
|
return registry.get( key );
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,13 @@ import java.util.UUID;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
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.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.UUIDTypeDescriptor;
|
import org.hibernate.type.descriptor.java.UUIDTypeDescriptor;
|
||||||
import org.hibernate.type.descriptor.sql.BasicBinder;
|
import org.hibernate.type.descriptor.sql.BasicBinder;
|
||||||
import org.hibernate.type.descriptor.sql.BasicExtractor;
|
import org.hibernate.type.descriptor.sql.BasicExtractor;
|
||||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
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
|
* 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;
|
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) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,9 +16,14 @@ import org.hibernate.internal.util.compare.EqualsHelper;
|
||||||
/**
|
/**
|
||||||
* Abstract adapter for Java type descriptors.
|
* 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
|
* @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 Class<T> type;
|
||||||
private final MutabilityPlan<T> mutabilityPlan;
|
private final MutabilityPlan<T> mutabilityPlan;
|
||||||
private final Comparator<T> comparator;
|
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> {
|
public class EnumJavaTypeDescriptor<T extends Enum> extends AbstractTypeDescriptor<T> {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected EnumJavaTypeDescriptor(Class<T> type) {
|
public EnumJavaTypeDescriptor(Class<T> type) {
|
||||||
super( type, ImmutableMutabilityPlan.INSTANCE );
|
super( type, ImmutableMutabilityPlan.INSTANCE );
|
||||||
//JavaTypeDescriptorRegistry.INSTANCE.addDescriptor( this );
|
//JavaTypeDescriptorRegistry.INSTANCE.addDescriptor( this );
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ package org.hibernate.type.descriptor.java;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import org.hibernate.internal.util.compare.ComparableComparator;
|
||||||
|
import org.hibernate.internal.util.compare.EqualsHelper;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,17 +39,18 @@ public interface JavaTypeDescriptor<T> extends Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the mutability plan for this Java type.
|
* 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.
|
* 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.
|
* Extract a proper hash code for this value.
|
||||||
|
@ -56,7 +59,12 @@ public interface JavaTypeDescriptor<T> extends Serializable {
|
||||||
*
|
*
|
||||||
* @return The extracted hash code.
|
* @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
|
* 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.
|
* @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.
|
* Extract a loggable representation of the value.
|
||||||
|
@ -75,11 +85,15 @@ public interface JavaTypeDescriptor<T> extends Serializable {
|
||||||
*
|
*
|
||||||
* @return The loggable representation
|
* @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.
|
* 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.
|
* @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.
|
* Wrap a value as our handled Java type.
|
||||||
|
@ -110,5 +124,5 @@ public interface JavaTypeDescriptor<T> extends Serializable {
|
||||||
*
|
*
|
||||||
* @return The wrapped value.
|
* @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;
|
package org.hibernate.type.descriptor.java;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
@ -16,6 +15,7 @@ import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.spi.RegistryHelper;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,8 +84,7 @@ public class JavaTypeDescriptorRegistry implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private JavaTypeDescriptor addDescriptorInternal(JavaTypeDescriptor descriptor) {
|
private JavaTypeDescriptor addDescriptorInternal(JavaTypeDescriptor descriptor) {
|
||||||
JavaTypeDescriptor javaTypeDescriptor = descriptorsByClass.put( descriptor.getJavaType(), descriptor );
|
return descriptorsByClass.put( descriptor.getJavaType(), descriptor );
|
||||||
return javaTypeDescriptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,43 +112,26 @@ public class JavaTypeDescriptorRegistry implements Serializable {
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> JavaTypeDescriptor<T> getDescriptor(Class<T> cls) {
|
public <J> JavaTypeDescriptor<J> getDescriptor(Class<J> cls) {
|
||||||
if ( cls == null ) {
|
return RegistryHelper.INSTANCE.resolveDescriptor(
|
||||||
throw new IllegalArgumentException( "Class passed to locate Java type descriptor cannot be null" );
|
descriptorsByClass,
|
||||||
}
|
cls,
|
||||||
|
() -> {
|
||||||
|
if ( Serializable.class.isAssignableFrom( cls ) ) {
|
||||||
|
return new SerializableTypeDescriptor( cls );
|
||||||
|
}
|
||||||
|
|
||||||
JavaTypeDescriptor<T> descriptor = descriptorsByClass.get( cls );
|
log.debugf(
|
||||||
if ( descriptor != null ) {
|
"Could not find matching JavaTypeDescriptor for requested Java class [%s]; using fallback. " +
|
||||||
return descriptor;
|
"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() ) {
|
return new FallbackJavaTypeDescriptor<>( cls );
|
||||||
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()
|
|
||||||
);
|
);
|
||||||
checkEqualsAndHashCode( cls );
|
|
||||||
|
|
||||||
return new FallbackJavaTypeDescriptor<>( cls );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@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
|
// 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 class SerializableMutabilityPlan<S extends Serializable> extends MutableMutabilityPlan<S> {
|
||||||
|
public static final SerializableMutabilityPlan<Serializable> INSTANCE = new SerializableMutabilityPlan<>();
|
||||||
|
|
||||||
public static final SerializableMutabilityPlan<Serializable> INSTANCE
|
private SerializableMutabilityPlan() {
|
||||||
= new SerializableMutabilityPlan<Serializable>( );
|
|
||||||
|
|
||||||
public SerializableMutabilityPlan() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -124,7 +122,7 @@ public class SerializableTypeDescriptor<T extends Serializable> extends Abstract
|
||||||
throw new HibernateException( e );
|
throw new HibernateException( e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( getJavaTypeClass().isInstance( value ) ) {
|
else if ( getJavaType().isInstance( value ) ) {
|
||||||
return (T) value;
|
return (T) value;
|
||||||
}
|
}
|
||||||
throw unknownWrap( value.getClass() );
|
throw unknownWrap( value.getClass() );
|
||||||
|
@ -136,6 +134,6 @@ public class SerializableTypeDescriptor<T extends Serializable> extends Abstract
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked" })
|
@SuppressWarnings({ "unchecked" })
|
||||||
protected T fromBytes(byte[] bytes) {
|
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;
|
package org.hibernate.type.descriptor.java.spi;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basically a map from {@link Class} -> {@link JavaTypeDescriptor}
|
* Basically a map from {@link Class} -> {@link JavaTypeDescriptor}
|
||||||
*
|
*
|
||||||
|
@ -19,25 +22,41 @@ import org.hibernate.type.spi.TypeConfiguration;
|
||||||
*
|
*
|
||||||
* @since 5.3
|
* @since 5.3
|
||||||
*/
|
*/
|
||||||
public class JavaTypeDescriptorRegistry
|
public class JavaTypeDescriptorRegistry implements Serializable {
|
||||||
extends org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry
|
private static final Logger log = Logger.getLogger( JavaTypeDescriptorRegistry.class );
|
||||||
implements Serializable {
|
|
||||||
|
|
||||||
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) {
|
public JavaTypeDescriptorRegistry(TypeConfiguration typeConfiguration) {
|
||||||
this.typeConfiguration = typeConfiguration;
|
|
||||||
javaTypeDescriptorRegistry = org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry.INSTANCE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> JavaTypeDescriptor<T> getDescriptor(Class<T> javaType) {
|
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) {
|
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.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
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.
|
* 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();
|
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
|
* Get the binder (setting JDBC in-going parameter values) capable of handling values of the type described by the
|
||||||
* passed descriptor.
|
* passed descriptor.
|
||||||
|
|
|
@ -151,7 +151,7 @@ public class SqlTypeDescriptorRegistry implements Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
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 );
|
return VarbinaryTypeDescriptor.INSTANCE.getBinder( javaTypeDescriptor );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ public class SqlTypeDescriptorRegistry implements Serializable {
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public ValueExtractor getExtractor(JavaTypeDescriptor javaTypeDescriptor) {
|
public ValueExtractor getExtractor(JavaTypeDescriptor javaTypeDescriptor) {
|
||||||
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaTypeClass() ) ) {
|
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaType() ) ) {
|
||||||
return VarbinaryTypeDescriptor.INSTANCE.getExtractor( javaTypeDescriptor );
|
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(
|
String.format(
|
||||||
"%s (%s) -> %s",
|
"%s (%s) -> %s",
|
||||||
propertyBinding.getName(),
|
propertyBinding.getName(),
|
||||||
javaTypeDescriptor.getJavaTypeClass().getSimpleName(),
|
javaTypeDescriptor.getJavaType().getSimpleName(),
|
||||||
javaTypeDescriptor.toString( propertyBinding.getGetter( TheEntity.class ).get( theEntity ) )
|
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
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
|
@ -8,13 +10,27 @@
|
||||||
apply from: rootProject.file( 'gradle/published-java-module.gradle' )
|
apply from: rootProject.file( 'gradle/published-java-module.gradle' )
|
||||||
apply plugin: 'hibernate-matrix-testing'
|
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'
|
description = 'Integrate support for Spatial/GIS data into Hibernate O/RM'
|
||||||
|
|
||||||
dependencies {
|
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) {
|
compile(libraries.dom4j) {
|
||||||
transitive = false
|
transitive = false
|
||||||
}
|
}
|
||||||
|
@ -40,3 +56,25 @@ sourceSets.test.resources {
|
||||||
setSrcDirs(['src/test/java', 'src/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;
|
package org.hibernate.spatial;
|
||||||
|
|
||||||
|
import java.sql.Types;
|
||||||
|
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;
|
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.Geometry;
|
||||||
import org.geolatte.geom.codec.Wkt;
|
import org.geolatte.geom.codec.Wkt;
|
||||||
|
@ -35,6 +38,11 @@ public class GeolatteGeometryJavaTypeDescriptor extends AbstractTypeDescriptor<G
|
||||||
super( Geometry.class );
|
super( Geometry.class );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlTypeDescriptor getJdbcRecommendedSqlType(JdbcRecommendedSqlTypeMappingContext context) {
|
||||||
|
return context.getTypeConfiguration().getSqlTypeDescriptorRegistry().getDescriptor( Types.ARRAY );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(Geometry value) {
|
public String toString(Geometry value) {
|
||||||
return value.toString();
|
return value.toString();
|
||||||
|
|
|
@ -27,6 +27,18 @@ import org.geolatte.geom.Polygon;
|
||||||
*/
|
*/
|
||||||
public class GeolatteGeometryType extends AbstractSingleColumnStandardBasicType<Geometry> implements Spatial {
|
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}
|
* Constructs an instance with the specified {@code SqlTypeDescriptor}
|
||||||
*
|
*
|
||||||
|
@ -38,17 +50,7 @@ public class GeolatteGeometryType extends AbstractSingleColumnStandardBasicType<
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getRegistrationKeys() {
|
public String[] getRegistrationKeys() {
|
||||||
return new String[] {
|
return 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"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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