HHH-18060 - HbXmlTransformer work
* "special" basic type handling
This commit is contained in:
parent
d25f028222
commit
875e84b930
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
Loading…
Reference in New Issue