HHH-18060 - HbXmlTransformer work

* "special" basic type handling
This commit is contained in:
Steve Ebersole 2024-06-07 11:27:48 -05:00
parent d25f028222
commit 875e84b930
7 changed files with 579 additions and 6 deletions

View File

@ -10,8 +10,30 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.URL;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.NClob;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.Year;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Currency;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.UUID;
import java.util.function.Consumer;
@ -136,6 +158,41 @@ import org.hibernate.models.spi.MutableClassDetails;
import org.hibernate.models.spi.MutableMemberDetails;
import org.hibernate.models.spi.SourceModelBuildingContext;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.java.BasicJavaType;
import org.hibernate.type.descriptor.java.BigDecimalJavaType;
import org.hibernate.type.descriptor.java.BigIntegerJavaType;
import org.hibernate.type.descriptor.java.BlobJavaType;
import org.hibernate.type.descriptor.java.BooleanJavaType;
import org.hibernate.type.descriptor.java.ByteJavaType;
import org.hibernate.type.descriptor.java.CalendarJavaType;
import org.hibernate.type.descriptor.java.CharacterJavaType;
import org.hibernate.type.descriptor.java.ClassJavaType;
import org.hibernate.type.descriptor.java.ClobJavaType;
import org.hibernate.type.descriptor.java.CurrencyJavaType;
import org.hibernate.type.descriptor.java.DateJavaType;
import org.hibernate.type.descriptor.java.DoubleJavaType;
import org.hibernate.type.descriptor.java.DurationJavaType;
import org.hibernate.type.descriptor.java.InetAddressJavaType;
import org.hibernate.type.descriptor.java.InstantJavaType;
import org.hibernate.type.descriptor.java.IntegerJavaType;
import org.hibernate.type.descriptor.java.LocalDateJavaType;
import org.hibernate.type.descriptor.java.LocalDateTimeJavaType;
import org.hibernate.type.descriptor.java.LocalTimeJavaType;
import org.hibernate.type.descriptor.java.LocaleJavaType;
import org.hibernate.type.descriptor.java.LongJavaType;
import org.hibernate.type.descriptor.java.NClobJavaType;
import org.hibernate.type.descriptor.java.OffsetDateTimeJavaType;
import org.hibernate.type.descriptor.java.OffsetTimeJavaType;
import org.hibernate.type.descriptor.java.ShortJavaType;
import org.hibernate.type.descriptor.java.StringJavaType;
import org.hibernate.type.descriptor.java.TimeZoneJavaType;
import org.hibernate.type.descriptor.java.UUIDJavaType;
import org.hibernate.type.descriptor.java.UrlJavaType;
import org.hibernate.type.descriptor.java.YearJavaType;
import org.hibernate.type.descriptor.java.ZoneIdJavaType;
import org.hibernate.type.descriptor.java.ZoneOffsetJavaType;
import org.hibernate.type.descriptor.java.ZonedDateTimeJavaType;
import org.hibernate.usertype.UserType;
import jakarta.persistence.AssociationOverride;
import jakarta.persistence.AttributeOverride;
@ -146,6 +203,7 @@ import jakarta.persistence.EnumType;
import jakarta.persistence.Index;
import jakarta.persistence.PrimaryKeyJoinColumn;
import jakarta.persistence.SecondaryTable;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;
import jakarta.persistence.UniqueConstraint;
import org.checkerframework.checker.nullness.qual.Nullable;
@ -244,20 +302,305 @@ public class XmlAnnotationHelper {
JaxbUserTypeImpl jaxbType,
MutableMemberDetails memberDetails,
XmlDocumentContext xmlDocumentContext) {
if ( jaxbType == null ) {
if ( jaxbType == null || StringHelper.isEmpty( jaxbType.getValue() ) ) {
return;
}
final boolean wasSpecialCase = handleSpecialBasicTypeCases( jaxbType, memberDetails, xmlDocumentContext );
if ( wasSpecialCase ) {
return;
}
final ClassDetails userTypeImpl = resolveJavaType( jaxbType.getValue(), xmlDocumentContext );
assert userTypeImpl.isImplementor( UserType.class );
final TypeAnnotation typeAnn = (TypeAnnotation) memberDetails.applyAnnotationUsage(
HibernateAnnotations.TYPE,
xmlDocumentContext.getModelBuildingContext()
);
final ClassDetails userTypeImpl = resolveJavaType( jaxbType.getValue(), xmlDocumentContext );
typeAnn.value( userTypeImpl.toJavaClass() );
typeAnn.parameters( collectParameters( jaxbType.getParameters(), xmlDocumentContext ) );
}
private static boolean handleSpecialBasicTypeCases(
JaxbUserTypeImpl jaxbType,
MutableMemberDetails memberDetails,
XmlDocumentContext xmlDocumentContext) {
if ( jaxbType.getValue().equalsIgnoreCase( "char" )
|| jaxbType.getValue().equalsIgnoreCase( "character" )
|| Character.class.getName().equalsIgnoreCase( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, CharacterJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "string" )
|| String.class.getName().equalsIgnoreCase( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, StringJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "byte" )
|| Byte.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, ByteJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "boolean" )
|| Boolean.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, BooleanJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "short" )
|| Short.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, ShortJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "int" )
|| jaxbType.getValue().equalsIgnoreCase( "integer" )
|| Integer.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, IntegerJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "long" )
|| Long.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, LongJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "double" )
|| Double.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, DoubleJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "float" )
|| Float.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, DoubleJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "biginteger" )
|| jaxbType.getValue().equalsIgnoreCase( "big_integer" )
|| BigInteger.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, BigIntegerJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "bigdecimal" )
|| jaxbType.getValue().equalsIgnoreCase( "big_decimal" )
|| BigDecimal.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, BigDecimalJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "uuid" )
|| UUID.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, UUIDJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "url" )
|| URL.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, UrlJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "inet" )
|| jaxbType.getValue().equalsIgnoreCase( "inetaddress" )
|| jaxbType.getValue().equalsIgnoreCase( "inet_address" )
|| InetAddress.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, InetAddressJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "currency" )
|| Currency.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, CurrencyJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "locale" )
|| Locale.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, LocaleJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "class" )
|| Class.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, ClassJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "blob" )
|| Blob.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, BlobJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "clob" )
|| Clob.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, ClobJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "nclob" )
|| NClob.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, NClobJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "instant" )
|| Instant.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, InstantJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "duration" )
|| Duration.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, DurationJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "year" )
|| Year.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, YearJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "localdatetime" )
|| jaxbType.getValue().equalsIgnoreCase( "local_date_time" )
|| LocalDateTime.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, LocalDateTimeJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "localdate" )
|| jaxbType.getValue().equalsIgnoreCase( "local_date" )
|| LocalDate.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, LocalDateJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "localtime" )
|| jaxbType.getValue().equalsIgnoreCase( "local_time" )
|| LocalTime.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, LocalTimeJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "zoneddatetime" )
|| jaxbType.getValue().equalsIgnoreCase( "zoned_date_time" )
|| ZonedDateTime.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, ZonedDateTimeJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "offsetdatetime" )
|| jaxbType.getValue().equalsIgnoreCase( "offset_date_time" )
|| OffsetDateTime.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, OffsetDateTimeJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "offsettime" )
|| jaxbType.getValue().equalsIgnoreCase( "offset_time" )
|| OffsetTime.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, OffsetTimeJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "zoneid" )
|| jaxbType.getValue().equalsIgnoreCase( "zone_id" )
|| ZoneId.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, ZoneIdJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "zoneoffset" )
|| jaxbType.getValue().equalsIgnoreCase( "zone_offset" )
|| ZoneOffset.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, ZoneOffsetJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "timestamp" )
|| jaxbType.getValue().equalsIgnoreCase( "time_stamp" )
|| java.util.Date.class.getName().equals( jaxbType.getValue() )
|| Timestamp.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, DateJavaType.class, xmlDocumentContext );
applyTemporalPrecision( memberDetails, TemporalType.TIMESTAMP, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "date" )
|| java.sql.Date.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, DateJavaType.class, xmlDocumentContext );
applyTemporalPrecision( memberDetails, TemporalType.DATE, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "time" )
|| java.sql.Time.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, DateJavaType.class, xmlDocumentContext );
applyTemporalPrecision( memberDetails, TemporalType.TIME, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "calendar" )
|| jaxbType.getValue().equalsIgnoreCase( "gregoriancalendar" )
|| jaxbType.getValue().equalsIgnoreCase( "gregorian_calendar" )
|| Calendar.class.getName().equals( jaxbType.getValue() )
|| GregorianCalendar.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, CalendarJavaType.class, xmlDocumentContext );
return true;
}
if ( jaxbType.getValue().equalsIgnoreCase( "timezone" )
|| jaxbType.getValue().equalsIgnoreCase( "time_zone" )
|| TimeZone.class.getName().equals( jaxbType.getValue() ) ) {
applyJavaTypeAnnotation( memberDetails, TimeZoneJavaType.class, xmlDocumentContext );
return true;
}
return false;
}
private static void applyJavaTypeAnnotation(
MutableMemberDetails memberDetails,
Class<? extends BasicJavaType<?>> descriptor,
XmlDocumentContext xmlDocumentContext) {
final JavaTypeAnnotation javaTypeAnnotation = (JavaTypeAnnotation) memberDetails.applyAnnotationUsage(
HibernateAnnotations.JAVA_TYPE,
xmlDocumentContext.getModelBuildingContext()
);
javaTypeAnnotation.value( descriptor );
}
private static void applyTemporalPrecision(MutableMemberDetails memberDetails, TemporalType temporalType, XmlDocumentContext xmlDocumentContext) {
final Temporal directUsage = memberDetails.getDirectAnnotationUsage( Temporal.class );
if ( directUsage != null ) {
// make sure they match
if ( directUsage.value() != temporalType ) {
throw new org.hibernate.MappingException( String.format(
Locale.ROOT,
"Mismatch in expected TemporalType on %s; found %s and %s",
memberDetails,
directUsage.value(),
temporalType
) );
}
return;
}
final TemporalJpaAnnotation temporalAnnotation = (TemporalJpaAnnotation) memberDetails.applyAnnotationUsage(
JpaAnnotations.TEMPORAL,
xmlDocumentContext.getModelBuildingContext()
);
temporalAnnotation.value( temporalType );
}
private static final Parameter[] NO_PARAMETERS = new Parameter[0];
public static Parameter[] collectParameters(

View File

@ -12,6 +12,7 @@ import org.hibernate.boot.models.annotations.internal.BasicJpaAnnotation;
import org.hibernate.boot.models.xml.internal.XmlAnnotationHelper;
import org.hibernate.boot.models.xml.internal.XmlProcessingHelper;
import org.hibernate.boot.models.xml.spi.XmlDocumentContext;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.models.spi.MutableClassDetails;
import org.hibernate.models.spi.MutableMemberDetails;
@ -33,8 +34,12 @@ public class BasicIdAttributeProcessing {
AccessType classAccessType,
XmlDocumentContext xmlDocumentContext) {
final AccessType accessType = coalesce( jaxbId.getAccess(), classAccessType );
final String idAttributeName = StringHelper.isNotEmpty( jaxbId.getName() )
? jaxbId.getName()
: "id";
final MutableMemberDetails memberDetails = XmlProcessingHelper.getAttributeMember(
jaxbId.getName(),
idAttributeName,
accessType,
declarer
);

View File

@ -0,0 +1,25 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.boot.models.hbm.type;
import java.net.URL;
import java.util.List;
import java.util.UUID;
/**
* @author Steve Ebersole
*/
public class EntityWithElementCollections {
private Integer id;
private String name;
private List<String> listOfStrings;
private List<Integer> listOfIntegers;
private List<Double> listOfDoubles;
private List<URL> listOfUrls;
private List<UUID> listOfUuids;
}

View File

@ -0,0 +1,127 @@
/*
* 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.orm.test.boot.models.hbm.type;
import org.hibernate.cfg.MappingSettings;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.RootClass;
import org.hibernate.type.BasicType;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.java.BasicJavaType;
import org.hibernate.type.descriptor.java.BooleanJavaType;
import org.hibernate.type.descriptor.java.ClobJavaType;
import org.hibernate.type.descriptor.java.DoubleJavaType;
import org.hibernate.type.descriptor.java.InstantJavaType;
import org.hibernate.type.descriptor.java.IntegerJavaType;
import org.hibernate.type.descriptor.java.JdbcDateJavaType;
import org.hibernate.type.descriptor.java.JdbcTimeJavaType;
import org.hibernate.type.descriptor.java.JdbcTimestampJavaType;
import org.hibernate.type.descriptor.java.ShortJavaType;
import org.hibernate.type.descriptor.java.StringJavaType;
import org.hibernate.type.descriptor.java.UUIDJavaType;
import org.hibernate.type.descriptor.java.UrlJavaType;
import org.hibernate.testing.orm.domain.gambit.EntityOfBasics;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @implNote Limited to H2 simply because some Dialects will map some of these to
* minor differences in SQL/JDBC types, and largely such differences are unimportant here
*
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
@RequiresDialect( H2Dialect.class )
public class SpecialTypeTransformationTests {
@Test
@ServiceRegistry(settings = {
@Setting(name = MappingSettings.JAVA_TIME_USE_DIRECT_JDBC, value = "true"),
// SqlTypes.INSTANT
@Setting(name = MappingSettings.PREFERRED_INSTANT_JDBC_TYPE, value = "3008")
} )
@DomainModel(xmlMappings = "mappings/models/hbm/type/basics.xml")
void testBasicsHbmXml(DomainModelScope scope) {
scope.withHierarchy( EntityOfBasics.class, this::verify );
}
@Test
@ServiceRegistry(settings = {
@Setting(name = MappingSettings.JAVA_TIME_USE_DIRECT_JDBC, value = "true"),
// SqlTypes.INSTANT
@Setting(name = MappingSettings.PREFERRED_INSTANT_JDBC_TYPE, value = "3008"),
@Setting(name = MappingSettings.TRANSFORM_HBM_XML, value = "true")
} )
@DomainModel(xmlMappings = "mappings/models/hbm/type/basics.xml")
void testBasicsTransformed(DomainModelScope scope) {
scope.withHierarchy( EntityOfBasics.class, this::verify );
}
@Test
@ServiceRegistry
@DomainModel(xmlMappings = "mappings/models/hbm/type/element-collections.xml")
void testElementCollectionsHbmXml(DomainModelScope scope) {
scope.withHierarchy( EntityWithElementCollections.class, this::verifyElementCollections );
}
@Test
@ServiceRegistry(settings = @Setting(name = MappingSettings.TRANSFORM_HBM_XML, value = "true"))
@DomainModel(xmlMappings = "mappings/models/hbm/type/element-collections.xml")
void testElementCollectionsTransformed(DomainModelScope scope) {
scope.withHierarchy( EntityWithElementCollections.class, this::verifyElementCollections );
}
private void verify(RootClass rootClass) {
verify( (BasicType<?>) rootClass.getIdentifier().getType(), IntegerJavaType.class, SqlTypes.INTEGER );
verify( rootClass, "theBoolean", BooleanJavaType.class, SqlTypes.BOOLEAN );
verify( rootClass, "theString", StringJavaType.class, SqlTypes.VARCHAR );
verify( rootClass, "theInt", IntegerJavaType.class, SqlTypes.INTEGER );
verify( rootClass, "theInteger", IntegerJavaType.class, SqlTypes.INTEGER );
verify( rootClass, "theShort", ShortJavaType.class, SqlTypes.SMALLINT );
verify( rootClass, "theDouble", DoubleJavaType.class, SqlTypes.DOUBLE );
verify( rootClass, "theUrl", UrlJavaType.class, SqlTypes.VARCHAR );
verify( rootClass, "theClob", ClobJavaType.class, SqlTypes.CLOB );
verify( rootClass, "theInstant", InstantJavaType.class, SqlTypes.INSTANT );
verify( rootClass, "theDate", JdbcDateJavaType.class, SqlTypes.DATE );
verify( rootClass, "theTime", JdbcTimeJavaType.class, SqlTypes.TIME );
verify( rootClass, "theTimestamp", JdbcTimestampJavaType.class, SqlTypes.TIMESTAMP );
}
private void verify(RootClass rootClass, String attributeName, Class<? extends BasicJavaType<?>> expectedJavaType, int expectedJdbcTypeCode) {
final Property attribute = rootClass.getProperty( attributeName );
assertThat( attribute.getType() ).isInstanceOf( BasicType.class );
verify( (BasicType<?>) attribute.getType(), expectedJavaType, expectedJdbcTypeCode );
}
private void verifyElementCollections(RootClass rootClass) {
verifyElementCollection( rootClass, "listOfStrings", StringJavaType.class, SqlTypes.VARCHAR );
verifyElementCollection( rootClass, "listOfIntegers", IntegerJavaType.class, SqlTypes.INTEGER );
verifyElementCollection( rootClass, "listOfDoubles", DoubleJavaType.class, SqlTypes.DOUBLE );
verifyElementCollection( rootClass, "listOfUrls", UrlJavaType.class, SqlTypes.VARCHAR );
verifyElementCollection( rootClass, "listOfUuids", UUIDJavaType.class, SqlTypes.OTHER );
}
private void verifyElementCollection(RootClass rootClass, String name, Class<? extends BasicJavaType<?>> expectedJavaType, int expectedJdbcTypeCode) {
final Property property = rootClass.getProperty( name );
final Collection propertyValue = (Collection) property.getValue();
verify( (BasicType<?>) propertyValue.getElement().getType(), expectedJavaType, expectedJdbcTypeCode );
}
private void verify(BasicType<?> type, Class<? extends BasicJavaType<?>> expectedJavaType, int expectedJdbcTypeCode) {
assertThat( type.getJavaTypeDescriptor().getClass() ).isEqualTo( expectedJavaType );
assertThat( type.getJdbcType().getJdbcTypeCode() ).isEqualTo( expectedJdbcTypeCode );
}
}

View File

@ -16,8 +16,6 @@ hibernate.connection.autocommit false
hibernate.connection.initial_pool_size 0
hibernate.connection.pool_size 5
hibernate.transform_hbm_xml.enabled true
hibernate.show_sql true
hibernate.format_sql true
hibernate.highlight_sql true

View File

@ -0,0 +1,28 @@
<?xml version="1.0"?>
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
-->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping default-access="field">
<class name="org.hibernate.testing.orm.domain.gambit.EntityOfBasics">
<id type="integer"/>
<property name="theBoolean" type="boolean"/>
<property name="theString" type="string"/>
<property name="theInt" type="int"/>
<property name="theInteger" type="integer"/>
<property name="theShort" type="java.lang.Short"/>
<property name="theDouble" type="double"/>
<property name="theUrl" type="url"/>
<property name="theClob" type="clob"/>
<property name="theInstant" type="instant"/>
<property name="theDate" type="date"/>
<property name="theTime" type="time"/>
<property name="theTimestamp" type="timestamp"/>
</class>
</hibernate-mapping>

View File

@ -0,0 +1,47 @@
<?xml version="1.0"?>
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
-->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping default-access="field">
<class name="org.hibernate.orm.test.boot.models.hbm.type.EntityWithElementCollections">
<id type="integer"/>
<property name="name" type="string"/>
<list name="listOfStrings">
<key column="fk"/>
<index column="position"/>
<element column="strings" type="string"/>
</list>
<list name="listOfIntegers">
<key column="fk"/>
<index column="position"/>
<element column="numbers" type="integer"/>
</list>
<list name="listOfDoubles">
<key column="fk"/>
<index column="position"/>
<element column="numbers" type="double"/>
</list>
<list name="listOfUrls">
<key column="fk"/>
<index column="position"/>
<element column="numbers" type="url"/>
</list>
<list name="listOfUuids">
<key column="fk"/>
<index column="position"/>
<element column="numbers" type="uuid"/>
</list>
</class>
</hibernate-mapping>