From 9d927bb214065f9ddc3c75f5e696c9918f895bff Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 6 Dec 2025 23:35:41 +0100 Subject: [PATCH 01/10] use Class.cast() to remove all the horrible unchecked type casts in the JavaTypes --- .../type/AbstractStandardBasicType.java | 94 ++++++++----------- .../java/org/hibernate/type/EntityType.java | 4 +- .../java/AbstractClassJavaType.java | 2 +- .../type/descriptor/java/ArrayJavaType.java | 13 +-- .../descriptor/java/BigDecimalJavaType.java | 24 +++-- .../descriptor/java/BigIntegerJavaType.java | 24 +++-- .../type/descriptor/java/BlobJavaType.java | 20 ++-- .../type/descriptor/java/BooleanJavaType.java | 43 +++++---- .../java/BooleanPrimitiveArrayJavaType.java | 11 +-- .../descriptor/java/ByteArrayJavaType.java | 33 ++++--- .../type/descriptor/java/ByteJavaType.java | 20 ++-- .../descriptor/java/CalendarDateJavaType.java | 11 +-- .../descriptor/java/CalendarJavaType.java | 11 +-- .../descriptor/java/CalendarTimeJavaType.java | 11 +-- .../java/CharacterArrayJavaType.java | 18 ++-- .../descriptor/java/CharacterJavaType.java | 12 ++- .../type/descriptor/java/ClassJavaType.java | 10 +- .../type/descriptor/java/ClobJavaType.java | 20 ++-- .../descriptor/java/CurrencyJavaType.java | 10 +- .../type/descriptor/java/DateJavaType.java | 18 ++-- .../type/descriptor/java/DoubleJavaType.java | 24 +++-- .../java/DoublePrimitiveArrayJavaType.java | 16 ++-- .../descriptor/java/DurationJavaType.java | 16 ++-- .../type/descriptor/java/EnumJavaType.java | 13 ++- .../type/descriptor/java/FloatJavaType.java | 24 +++-- .../java/FloatPrimitiveArrayJavaType.java | 16 ++-- .../descriptor/java/InetAddressJavaType.java | 7 +- .../type/descriptor/java/InstantJavaType.java | 24 +++-- .../type/descriptor/java/IntegerJavaType.java | 24 +++-- .../java/IntegerPrimitiveArrayJavaType.java | 16 ++-- .../type/descriptor/java/JavaType.java | 34 +++++-- .../descriptor/java/JdbcDateJavaType.java | 5 + .../descriptor/java/JdbcTimeJavaType.java | 5 + .../java/JdbcTimestampJavaType.java | 5 + .../descriptor/java/LocalDateJavaType.java | 18 ++-- .../java/LocalDateTimeJavaType.java | 20 ++-- .../descriptor/java/LocalTimeJavaType.java | 20 ++-- .../type/descriptor/java/LocaleJavaType.java | 10 +- .../type/descriptor/java/LongJavaType.java | 24 +++-- .../java/LongPrimitiveArrayJavaType.java | 16 ++-- .../java/MutableMutabilityPlan.java | 2 +- .../type/descriptor/java/NClobJavaType.java | 20 ++-- .../descriptor/java/ObjectArrayJavaType.java | 8 +- .../type/descriptor/java/ObjectJavaType.java | 8 +- .../java/OffsetDateTimeJavaType.java | 28 +++--- .../descriptor/java/OffsetTimeJavaType.java | 26 ++--- .../java/PrimitiveByteArrayJavaType.java | 16 ++-- .../java/PrimitiveCharacterArrayJavaType.java | 18 ++-- .../descriptor/java/SerializableJavaType.java | 24 ++--- .../type/descriptor/java/ShortJavaType.java | 20 ++-- .../java/ShortPrimitiveArrayJavaType.java | 16 ++-- .../type/descriptor/java/StringJavaType.java | 22 +++-- .../descriptor/java/TimeZoneJavaType.java | 10 +- .../type/descriptor/java/UUIDJavaType.java | 12 ++- .../type/descriptor/java/UrlJavaType.java | 10 +- .../type/descriptor/java/YearJavaType.java | 14 ++- .../type/descriptor/java/ZoneIdJavaType.java | 10 +- .../descriptor/java/ZoneOffsetJavaType.java | 12 ++- .../java/ZonedDateTimeJavaType.java | 28 +++--- .../java/spi/BasicCollectionJavaType.java | 17 ++-- .../java/spi/CollectionJavaType.java | 6 +- .../java/spi/EmbeddableAggregateJavaType.java | 17 ++-- .../descriptor/java/spi/EntityJavaType.java | 11 ++- .../java/spi/FormatMapperBasedJavaType.java | 14 ++- .../java/spi/UnknownBasicJavaType.java | 9 +- .../type/descriptor/jdbc/ObjectJdbcType.java | 7 +- .../type/descriptor/jdbc/StructHelper.java | 3 +- .../type/descriptor/jdbc/StructJdbcType.java | 6 +- .../descriptor/jdbc/XmlArrayJdbcType.java | 3 +- .../type/descriptor/jdbc/XmlJdbcType.java | 6 +- .../jdbc/spi/BasicJdbcLiteralFormatter.java | 21 ++--- .../CompositeUserTypeJavaTypeWrapper.java | 5 +- .../internal/UserTypeJavaTypeWrapper.java | 15 ++- 73 files changed, 679 insertions(+), 511 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java index d41f3de19ffc..9c6434711ef7 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java @@ -55,18 +55,18 @@ public abstract class AbstractStandardBasicType public AbstractStandardBasicType(JdbcType jdbcType, JavaType javaType) { this.jdbcType = jdbcType; - this.sqlTypes = new int[] { jdbcType.getDdlTypeCode() }; this.javaType = javaType; + sqlTypes = new int[] { jdbcType.getDdlTypeCode() }; - this.jdbcValueBinder = jdbcType.getBinder( javaType ); - this.jdbcValueExtractor = jdbcType.getExtractor( javaType ); - this.jdbcLiteralFormatter = jdbcType.getJdbcLiteralFormatter( javaType ); + jdbcValueBinder = jdbcType.getBinder( javaType ); + jdbcValueExtractor = jdbcType.getExtractor( javaType ); + jdbcLiteralFormatter = jdbcType.getJdbcLiteralFormatter( javaType ); //A very simple dispatch optimisation, make these a constant: - this.javaTypeClass = javaType.getJavaTypeClass(); - this.mutabilityPlan = javaType.getMutabilityPlan(); - this.javatypeComparator = javaType.getComparator(); - this.typeForEqualsHashCode = javaType.useObjectEqualsHashCode() ? null : this; + javaTypeClass = javaType.getJavaTypeClass(); + mutabilityPlan = javaType.getMutabilityPlan(); + javatypeComparator = javaType.getComparator(); + typeForEqualsHashCode = javaType.useObjectEqualsHashCode() ? null : this; } @Override @@ -174,7 +174,6 @@ public final boolean isEqual(Object x, Object y, SessionFactoryImplementor facto } @Override - @SuppressWarnings("unchecked") public boolean isEqual(Object one, Object another) { if ( one == another ) { return true; @@ -186,19 +185,15 @@ else if ( typeForEqualsHashCode == null ) { return one.equals( another ); } else { - return javaType.areEqual( (T) one, (T) another ); + return javaType.areEqual( javaType.cast( one ), javaType.cast( another ) ); } } @Override - @SuppressWarnings("unchecked") - public int getHashCode(Object x) { - if ( typeForEqualsHashCode == null ) { - return x.hashCode(); - } - else { - return javaType.extractHashCode( (T) x ); - } + public int getHashCode(Object object) { + return typeForEqualsHashCode == null + ? object.hashCode() + : javaType.extractHashCode( javaType.cast( object ) ); } @Override @@ -212,9 +207,8 @@ public final int getHashCode(Object x, SessionFactoryImplementor factory) { } @Override - @SuppressWarnings("unchecked") public final int compare(Object x, Object y) { - return this.javatypeComparator.compare( (T) x, (T) y ); + return this.javatypeComparator.compare( javaType.cast( x ) , javaType.cast( y ) ); } @Override @@ -228,9 +222,11 @@ public final boolean isDirty(Object old, Object current, boolean[] checkable, Sh } protected final boolean isDirty(Object old, Object current) { - // MutableMutabilityPlan.INSTANCE is a special plan for which we always have to assume the value is dirty, - // because we can't actually copy a value, but have no knowledge about the mutability of the java type - return getMutabilityPlan() == MutableMutabilityPlan.INSTANCE || !isSame( old, current ); + // MutableMutabilityPlan.INSTANCE is a special plan for which we always + // have to assume the value is dirty, because we can't actually copy a + // value, but have no knowledge about the mutability of the java type + return getMutabilityPlan() == MutableMutabilityPlan.INSTANCE + || !isSame( old, current ); } @Override @@ -247,22 +243,23 @@ public final void nullSafeSet( PreparedStatement st, Object value, int index, - final SharedSessionContractImplementor session) throws SQLException { - //noinspection unchecked - nullSafeSet( st, (T) value, index, (WrapperOptions) session ); + final SharedSessionContractImplementor session) + throws SQLException { + nullSafeSet( st, javaType.cast( value ) , index, (WrapperOptions) session ); } - protected void nullSafeSet(PreparedStatement st, T value, int index, WrapperOptions options) throws SQLException { + protected void nullSafeSet(PreparedStatement st, T value, int index, WrapperOptions options) + throws SQLException { getJdbcValueBinder().bind( st, value, index, options ); } @Override - @SuppressWarnings("unchecked") public final String toLoggableString(Object value, SessionFactoryImplementor factory) { - if ( value == LazyPropertyInitializer.UNFETCHED_PROPERTY || !Hibernate.isInitialized( value ) ) { - return ""; - } - return javaType.extractLoggableRepresentation( (T) value ); + return value == LazyPropertyInitializer.UNFETCHED_PROPERTY + || !Hibernate.isInitialized( value ) + ? "" + : javaType.extractLoggableRepresentation( + javaType.coerce( value, factory::getTypeConfiguration ) ); } @Override @@ -271,9 +268,8 @@ public final boolean isMutable() { } @Override - @SuppressWarnings("unchecked") public final Object deepCopy(Object value, SessionFactoryImplementor factory) { - return deepCopy( (T) value ); + return deepCopy( javaType.cast( value ) ); } protected final T deepCopy(T value) { @@ -281,9 +277,8 @@ protected final T deepCopy(T value) { } @Override - @SuppressWarnings("unchecked") public final Serializable disassemble(Object value, SharedSessionContractImplementor session, Object owner) throws HibernateException { - return getMutabilityPlan().disassemble( (T) value, session ); + return getMutabilityPlan().disassemble( javaType.cast( value ) , session ); } @Override @@ -296,16 +291,14 @@ public final void beforeAssemble(Serializable cached, SharedSessionContractImple } @Override - @SuppressWarnings("unchecked") public final Object replace(Object original, Object target, SharedSessionContractImplementor session, Object owner, Map copyCache) { return original == null && target == null ? null - : javaType.getReplacement( (T) original, (T) target, session ); + : javaType.getReplacement( javaType.cast( original ) , javaType.cast( target ) , session ); } @Override - @SuppressWarnings("unchecked") public Object replace( Object original, Object target, @@ -314,6 +307,9 @@ public Object replace( Map copyCache, ForeignKeyDirection foreignKeyDirection) { return ForeignKeyDirection.FROM_PARENT == foreignKeyDirection + // TODO: use cast() .. currently failing on embeddable discriminators where + // the concrete class is passed in instead of its disciminator value +// ? javaType.getReplacement( javaType.cast( original ) , javaType.cast( target ) , session ) ? javaType.getReplacement( (T) original, (T) target, session ) : target; } @@ -325,20 +321,12 @@ public boolean canDoExtraction() { @Override public T extract(CallableStatement statement, int startIndex, final SharedSessionContractImplementor session) throws SQLException { - return getJdbcValueExtractor().extract( - statement, - startIndex, - session - ); + return getJdbcValueExtractor().extract( statement, startIndex, session ); } @Override public T extract(CallableStatement statement, String paramName, final SharedSessionContractImplementor session) throws SQLException { - return getJdbcValueExtractor().extract( - statement, - paramName, - session - ); + return getJdbcValueExtractor().extract( statement, paramName, session ); } @Override @@ -347,7 +335,8 @@ public void nullSafeSet( Object value, int index, boolean[] settable, - SharedSessionContractImplementor session) throws SQLException { + SharedSessionContractImplementor session) + throws SQLException { } @@ -356,9 +345,8 @@ public void nullSafeSet(CallableStatement st, T value, String name, SharedSessio nullSafeSet( st, value, name, (WrapperOptions) session ); } - @SuppressWarnings("unchecked") protected final void nullSafeSet(CallableStatement st, Object value, String name, WrapperOptions options) throws SQLException { - getJdbcValueBinder().bind( st, (T) value, name, options ); + getJdbcValueBinder().bind( st, javaType.cast( value ) , name, options ); } @Override @@ -379,7 +367,7 @@ public CastType getCastType() { // Due to that, we have to handle some conversions in wrap/unwrap of BooleanJavaType // and the cast type determination here. Note that we interpret the converter in ConvertedBasicTypeImpl // to properly determine the correct cast type - final JdbcType jdbcType = getJdbcType(); + final var jdbcType = getJdbcType(); final int jdbcTypeCode = jdbcType.getDdlTypeCode(); switch ( jdbcTypeCode ) { case Types.BIT: diff --git a/hibernate-core/src/main/java/org/hibernate/type/EntityType.java b/hibernate-core/src/main/java/org/hibernate/type/EntityType.java index f0dcaff0c920..12cc140f8bb9 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/EntityType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/EntityType.java @@ -461,7 +461,7 @@ private Object getUniqueKey(Object value, SharedSessionContractImplementor sessi if ( lazyInitializer != null ) { // If the value is a Proxy and the property access is field, the value returned by // attributeMapping.getAttributeMetadata().getPropertyAccess().getGetter().get( object ) - // is always null except for the id, we need the to use the proxy implementation to + // is always null except for the id, and we need to use the proxy implementation to // extract the property value. value = lazyInitializer.getImplementation(); } @@ -530,7 +530,7 @@ private String loggableString(Object entity, EntityPersister persister) { return associatedEntityName + "#" + entity; } else { - final StringBuilder result = new StringBuilder().append( associatedEntityName ); + final var result = new StringBuilder().append( associatedEntityName ); if ( persister.hasIdentifierProperty() ) { result.append( '#' ).append( identifierString( entity, persister ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractClassJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractClassJavaType.java index 430bb9b04f6e..e84b29138fb7 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractClassJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractClassJavaType.java @@ -81,7 +81,7 @@ public Class getJavaType() { } @Override - public Class getJavaTypeClass() { + public final Class getJavaTypeClass() { return getJavaType(); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java index 15fc1675d5ec..323d9312f228 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java @@ -256,24 +256,21 @@ public X unwrap(T[] value, Class type, WrapperOptions options) { } if ( type.isInstance( value ) ) { - //noinspection unchecked - return (X) value; + return type.cast( value ); } else if ( type == byte[].class ) { - return (X) toBytes( value ); + return type.cast( toBytes( value ) ); } else if ( type == BinaryStream.class ) { - //noinspection unchecked - return (X) new ArrayBackedBinaryStream( toBytes( value ) ); + return type.cast( new ArrayBackedBinaryStream( toBytes( value ) ) ); } else if ( type.isArray() ) { final var preferredJavaTypeClass = type.getComponentType(); - final Object[] unwrapped = (Object[]) newInstance( preferredJavaTypeClass, value.length ); + final var unwrapped = (Object[]) newInstance( preferredJavaTypeClass, value.length ); for ( int i = 0; i < value.length; i++ ) { unwrapped[i] = getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ); } - //noinspection unchecked - return (X) unwrapped; + return type.cast( unwrapped ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BigDecimalJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BigDecimalJavaType.java index 8accc2bf5555..c04e276c3de9 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BigDecimalJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BigDecimalJavaType.java @@ -37,6 +37,11 @@ public boolean isInstance(Object value) { return value instanceof BigDecimal; } + @Override + public BigDecimal cast(Object value) { + return (BigDecimal) value; + } + @Override public boolean areEqual(BigDecimal one, BigDecimal another) { return one == another @@ -48,37 +53,36 @@ public int extractHashCode(BigDecimal value) { return value.intValue(); } - @SuppressWarnings("unchecked") public X unwrap(BigDecimal value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( BigDecimal.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( BigInteger.class.isAssignableFrom( type ) ) { - return (X) value.toBigIntegerExact(); + return type.cast( value.toBigIntegerExact() ); } if ( Byte.class.isAssignableFrom( type ) ) { - return (X) Byte.valueOf( value.byteValue() ); + return type.cast( value.byteValue() ); } if ( Short.class.isAssignableFrom( type ) ) { - return (X) Short.valueOf( value.shortValue() ); + return type.cast( value.shortValue() ); } if ( Integer.class.isAssignableFrom( type ) ) { - return (X) Integer.valueOf( value.intValue() ); + return type.cast( value.intValue() ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( value.longValue() ); + return type.cast( value.longValue() ); } if ( Double.class.isAssignableFrom( type ) ) { - return (X) Double.valueOf( value.doubleValue() ); + return type.cast( value.doubleValue() ); } if ( Float.class.isAssignableFrom( type ) ) { - return (X) Float.valueOf( value.floatValue() ); + return type.cast( value.floatValue() ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) value.toString(); + return type.cast( value.toString() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BigIntegerJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BigIntegerJavaType.java index 5f9eae0892c6..02cbb5d930b1 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BigIntegerJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BigIntegerJavaType.java @@ -39,43 +39,47 @@ public boolean isInstance(Object value) { return value instanceof BigInteger; } + @Override + public BigInteger cast(Object value) { + return (BigInteger) value; + } + @Override public int extractHashCode(BigInteger value) { return value.intValue(); } @Override - @SuppressWarnings("unchecked") public X unwrap(BigInteger value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( BigInteger.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( BigDecimal.class.isAssignableFrom( type ) ) { - return (X) new BigDecimal( value ); + return type.cast( new BigDecimal( value ) ); } if ( Byte.class.isAssignableFrom( type ) ) { - return (X) Byte.valueOf( value.byteValue() ); + return type.cast( Byte.valueOf( value.byteValue() ) ); } if ( Short.class.isAssignableFrom( type ) ) { - return (X) Short.valueOf( value.shortValue() ); + return type.cast( value.shortValue() ); } if ( Integer.class.isAssignableFrom( type ) ) { - return (X) Integer.valueOf( value.intValue() ); + return type.cast( value.intValue() ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( value.longValue() ); + return type.cast( value.longValue() ); } if ( Double.class.isAssignableFrom( type ) ) { - return (X) Double.valueOf( value.doubleValue() ); + return type.cast( value.doubleValue() ); } if ( Float.class.isAssignableFrom( type ) ) { - return (X) Float.valueOf( value.floatValue() ); + return type.cast( value.floatValue() ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) value.toString(); + return type.cast( value.toString() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BlobJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BlobJavaType.java index 22a6c5ed834c..823b664dd31d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BlobJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BlobJavaType.java @@ -70,6 +70,11 @@ public boolean isInstance(Object value) { return value instanceof Blob; } + @Override + public Blob cast(Object value) { + return (Blob) value; + } + @Override public String extractLoggableRepresentation(Blob value) { return value == null ? "null" : "{blob}"; @@ -109,7 +114,6 @@ public Blob getReplacement(Blob original, Blob target, SharedSessionContractImpl } @Override - @SuppressWarnings("unchecked") public X unwrap(Blob value, Class type, WrapperOptions options) { if ( value == null ) { return null; @@ -117,17 +121,17 @@ public X unwrap(Blob value, Class type, WrapperOptions options) { try { if ( Blob.class.isAssignableFrom( type ) ) { - return (X) options.getLobCreator().toJdbcBlob( value ); + return type.cast( options.getLobCreator().toJdbcBlob( value ) ); } else if ( byte[].class.isAssignableFrom( type )) { if (value instanceof BlobImplementer blobImplementer) { // if the incoming Blob is a wrapper, just grab the bytes from its BinaryStream - return (X) blobImplementer.getUnderlyingStream().getBytes(); + return type.cast( blobImplementer.getUnderlyingStream().getBytes() ); } else { try { // otherwise extract the bytes from the stream manually - return (X) value.getBinaryStream().readAllBytes(); + return type.cast( value.getBinaryStream().readAllBytes() ); } catch ( IOException e ) { throw new HibernateException( "IOException occurred reading a binary value", e ); @@ -136,20 +140,20 @@ else if ( byte[].class.isAssignableFrom( type )) { } else if ( BinaryStream.class.isAssignableFrom( type ) ) { if (value instanceof BlobImplementer blobImplementer) { - return (X) blobImplementer.getUnderlyingStream(); + return type.cast( blobImplementer.getUnderlyingStream() ); } else { - return (X) new StreamBackedBinaryStream( value.getBinaryStream(), value.length() ); + return type.cast( new StreamBackedBinaryStream( value.getBinaryStream(), value.length() ) ); } } else if ( InputStream.class.isAssignableFrom( type ) ) { if (value instanceof BlobImplementer blobImplementer) { // if the incoming Blob is a wrapper, just pass along its BinaryStream - return (X) blobImplementer.getUnderlyingStream().getInputStream(); + return type.cast( blobImplementer.getUnderlyingStream().getInputStream() ); } else { // otherwise we need to build a BinaryStream... - return (X) value.getBinaryStream(); + return type.cast( value.getBinaryStream() ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanJavaType.java index 49466879b8a3..3bc1e90b605b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanJavaType.java @@ -10,6 +10,7 @@ import org.hibernate.type.descriptor.java.spi.PrimitiveJavaType; import org.hibernate.type.descriptor.jdbc.JdbcType; +import static java.lang.Boolean.parseBoolean; import static java.lang.Character.toUpperCase; import static org.hibernate.internal.util.CharSequenceHelper.regionMatchesIgnoreCase; @@ -59,7 +60,7 @@ public String toString(Boolean value) { @Override public Boolean fromString(CharSequence string) { - return Boolean.valueOf( string.toString() ); + return parseBoolean( string.toString() ); } @Override @@ -67,6 +68,11 @@ public boolean isInstance(Object value) { return value instanceof Boolean; } + @Override + public Boolean cast(Object value) { + return (Boolean) value; + } + @Override public Boolean fromEncodedString(CharSequence charSequence, int start, int end) { return switch ( charSequence.charAt( start ) ) { @@ -76,32 +82,31 @@ public Boolean fromEncodedString(CharSequence charSequence, int start, int end) }; } - @SuppressWarnings("unchecked") @Override public X unwrap(Boolean value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Boolean.class.isAssignableFrom( type ) || type == Object.class ) { - return (X) value; + return type.cast( value ); } if ( Byte.class.isAssignableFrom( type ) ) { - return (X) toByte( value ); + return type.cast( toByte( value ) ); } if ( Short.class.isAssignableFrom( type ) ) { - return (X) toShort( value ); + return type.cast( toShort( value ) ); } if ( Integer.class.isAssignableFrom( type ) ) { - return (X) toInteger( value ); + return type.cast( toInteger( value ) ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) toLong( value ); + return type.cast( toLong( value ) ); } if ( Character.class.isAssignableFrom( type ) ) { - return (X) Character.valueOf( value ? characterValueTrue : characterValueFalse ); + return type.cast( value ? characterValueTrue : characterValueFalse ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) (value ? stringValueTrue : stringValueFalse); + return type.cast( (value ? stringValueTrue : stringValueFalse) ); } throw unknownUnwrap( type ); } @@ -194,18 +199,18 @@ public int getDefaultSqlScale(Dialect dialect, JdbcType jdbcType) { public String getCheckCondition(String columnName, JdbcType jdbcType, BasicValueConverter converter, Dialect dialect) { if ( converter != null ) { if ( jdbcType.isString() ) { - final Object falseValue = converter.toRelationalValue( false ); - final Object trueValue = converter.toRelationalValue( true ); - final String[] values = getPossibleStringValues( converter, falseValue, trueValue ); - return dialect.getCheckCondition( columnName, values ); + return dialect.getCheckCondition( columnName, + getPossibleStringValues( converter, + converter.toRelationalValue( false ), + converter.toRelationalValue( true ) ) ); } else if ( jdbcType.isInteger() ) { @SuppressWarnings("unchecked") final var numericConverter = (BasicValueConverter) converter; - final Number falseValue = numericConverter.toRelationalValue( false ); - final Number trueValue = numericConverter.toRelationalValue( true ); - final Long[] values = getPossibleNumericValues( numericConverter, falseValue, trueValue ); - return dialect.getCheckCondition( columnName, values ); + return dialect.getCheckCondition( columnName, + getPossibleNumericValues( numericConverter, + numericConverter.toRelationalValue( false ), + numericConverter.toRelationalValue( true ) ) ); } } return null; @@ -221,7 +226,7 @@ private static Long[] getPossibleNumericValues( } catch ( NullPointerException ignored ) { } - final Long[] values = new Long[nullValue != null ? 3 : 2]; + final var values = new Long[nullValue != null ? 3 : 2]; values[0] = falseValue != null ? falseValue.longValue() : null; values[1] = trueValue != null ? trueValue.longValue() : null; if ( nullValue != null ) { @@ -240,7 +245,7 @@ private static String[] getPossibleStringValues( } catch ( NullPointerException ignored ) { } - final String[] values = new String[nullValue != null ? 3 : 2]; + final var values = new String[nullValue != null ? 3 : 2]; values[0] = falseValue != null ? falseValue.toString() : null; values[1] = trueValue != null ? trueValue.toString() : null; if ( nullValue != null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanPrimitiveArrayJavaType.java index 182ca0db7c6d..f8e48bdef5df 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanPrimitiveArrayJavaType.java @@ -106,7 +106,7 @@ public X unwrap(boolean[] value, Class type, WrapperOptions options) { } if ( type.isInstance( value ) ) { - return (X) value; + return type.cast( value ); } else if ( Object[].class.isAssignableFrom( type ) ) { final Class preferredJavaTypeClass = type.getComponentType(); @@ -114,16 +114,15 @@ else if ( Object[].class.isAssignableFrom( type ) ) { for ( int i = 0; i < value.length; i++ ) { unwrapped[i] = getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ); } - return (X) unwrapped; + return type.cast( unwrapped ); } else if ( type == byte[].class ) { // byte[] can only be requested if the value should be serialized - return (X) SerializationHelper.serialize( value ); + return type.cast( SerializationHelper.serialize( value ) ); } else if ( type == BinaryStream.class ) { // BinaryStream can only be requested if the value should be serialized - //noinspection unchecked - return (X) new ArrayBackedBinaryStream( SerializationHelper.serialize( value ) ); + return type.cast( new ArrayBackedBinaryStream( SerializationHelper.serialize( value ) ) ); } else if ( type.isArray() ) { final Class preferredJavaTypeClass = type.getComponentType(); @@ -131,7 +130,7 @@ else if ( type.isArray() ) { for ( int i = 0; i < value.length; i++ ) { Array.set( unwrapped, i, getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ) ); } - return (X) unwrapped; + return type.cast( unwrapped ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteArrayJavaType.java index ed0ca91b2e74..ac9efa800946 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteArrayJavaType.java @@ -19,6 +19,9 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; +import static java.lang.Byte.toUnsignedInt; +import static java.lang.Integer.toHexString; + /** * Descriptor for {@code Byte[]} handling, which disallows {@code null} elements. * This {@link JavaType} is useful if the domain model uses {@code Byte[]} and wants to map to {@link SqlTypes#VARBINARY}. @@ -38,6 +41,11 @@ public boolean isInstance(Object value) { return value instanceof byte[]; } + @Override + public Byte[] cast(Object value) { + return (Byte[]) value; + } + @Override public boolean areEqual(Byte[] one, Byte[] another) { return one == another @@ -57,22 +65,22 @@ public int extractHashCode(Byte[] bytes) { public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) { // match legacy behavior final var descriptor = indicators.getJdbcType( indicators.resolveJdbcTypeCode( SqlTypes.VARBINARY ) ); - return descriptor instanceof AdjustableJdbcType - ? ( (AdjustableJdbcType) descriptor ).resolveIndicatedType( indicators, this ) + return descriptor instanceof AdjustableJdbcType adjustableJdbcType + ? adjustableJdbcType.resolveIndicatedType( indicators, this ) : descriptor; } @Override public String toString(Byte[] bytes) { - final StringBuilder buf = new StringBuilder(); + final var string = new StringBuilder(); for ( Byte aByte : bytes ) { - final String hexStr = Integer.toHexString( Byte.toUnsignedInt(aByte) ); + final String hexStr = toHexString( toUnsignedInt( aByte ) ); if ( hexStr.length() == 1 ) { - buf.append( '0' ); + string.append( '0' ); } - buf.append( hexStr ); + string.append( hexStr ); } - return buf.toString(); + return string.toString(); } @Override public Byte[] fromString(CharSequence string) { @@ -90,26 +98,25 @@ public Byte[] fromString(CharSequence string) { return bytes; } - @SuppressWarnings("unchecked") @Override public X unwrap(Byte[] value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Byte[].class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( byte[].class.isAssignableFrom( type ) ) { - return (X) unwrapBytes( value ); + return type.cast( unwrapBytes( value ) ); } if ( InputStream.class.isAssignableFrom( type ) ) { - return (X) new ByteArrayInputStream( unwrapBytes( value ) ); + return type.cast( new ByteArrayInputStream( unwrapBytes( value ) ) ); } if ( BinaryStream.class.isAssignableFrom( type ) ) { - return (X) new ArrayBackedBinaryStream( unwrapBytes( value ) ); + return type.cast( new ArrayBackedBinaryStream( unwrapBytes( value ) ) ); } if ( Blob.class.isAssignableFrom( type ) ) { - return (X) options.getLobCreator().createBlob( unwrapBytes( value ) ); + return type.cast( options.getLobCreator().createBlob( unwrapBytes( value ) ) ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteJavaType.java index 1052f2a58d3f..ad7a4c5387f5 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteJavaType.java @@ -49,32 +49,36 @@ public boolean isInstance(Object value) { return value instanceof Byte; } - @SuppressWarnings("unchecked") + @Override + public Byte cast(Object value) { + return (Byte) value; + } + @Override public X unwrap(Byte value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Byte.class.isAssignableFrom( type ) || type == Object.class ) { - return (X) value; + return type.cast( value ); } if ( Short.class.isAssignableFrom( type ) ) { - return (X) Short.valueOf( value.shortValue() ); + return type.cast( value.shortValue() ); } if ( Integer.class.isAssignableFrom( type ) ) { - return (X) Integer.valueOf( value.intValue() ); + return type.cast( value.intValue() ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( value.longValue() ); + return type.cast( value.longValue() ); } if ( Double.class.isAssignableFrom( type ) ) { - return (X) Double.valueOf( value.doubleValue() ); + return type.cast( value.doubleValue() ); } if ( Float.class.isAssignableFrom( type ) ) { - return (X) Float.valueOf( value.floatValue() ); + return type.cast( value.floatValue() ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) value.toString(); + return type.cast( value.toString() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaType.java index 26d916fed2c0..c458b8b0c7c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaType.java @@ -88,25 +88,24 @@ public int extractHashCode(Calendar value) { return hashCode; } - @SuppressWarnings("unchecked") public X unwrap(Calendar value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Calendar.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( java.sql.Date.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Date( value.getTimeInMillis() ); + return type.cast( new java.sql.Date( value.getTimeInMillis() ) ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Time( value.getTimeInMillis() % 86_400_000 ); + return type.cast( new java.sql.Time( value.getTimeInMillis() % 86_400_000 ) ); } if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Timestamp( value.getTimeInMillis() ); + return type.cast( new java.sql.Timestamp( value.getTimeInMillis() ) ); } if ( Date.class.isAssignableFrom( type ) ) { - return (X) new Date( value.getTimeInMillis() ); + return type.cast( new Date( value.getTimeInMillis() ) ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaType.java index 517566d06959..10c49e839895 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaType.java @@ -105,25 +105,24 @@ public int extractHashCode(Calendar value) { return hashCode; } - @SuppressWarnings("unchecked") public X unwrap(Calendar value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Calendar.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( java.sql.Date.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Date( value.getTimeInMillis() ); + return type.cast( new java.sql.Date( value.getTimeInMillis() ) ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Time( value.getTimeInMillis() % 86_400_000 ); + return type.cast( new java.sql.Time( value.getTimeInMillis() % 86_400_000 ) ); } if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Timestamp( value.getTimeInMillis() ); + return type.cast( new java.sql.Timestamp( value.getTimeInMillis() ) ); } if ( java.util.Date.class.isAssignableFrom( type ) ) { - return (X) new java.util.Date( value.getTimeInMillis() ); + return type.cast( new java.util.Date( value.getTimeInMillis() ) ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaType.java index bd6a6e91fc30..e544c30f2e2c 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaType.java @@ -90,25 +90,24 @@ public int extractHashCode(Calendar value) { return hashCode; } - @SuppressWarnings("unchecked") public X unwrap(Calendar value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Calendar.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( java.sql.Date.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Date( value.getTimeInMillis() ); + return type.cast( new java.sql.Date( value.getTimeInMillis() ) ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Time( value.getTimeInMillis() % 86_400_000 ); + return type.cast( new java.sql.Time( value.getTimeInMillis() % 86_400_000 ) ); } if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Timestamp( value.getTimeInMillis() ); + return type.cast( new java.sql.Timestamp( value.getTimeInMillis() ) ); } if ( Date.class.isAssignableFrom( type ) ) { - return (X) new Date( value.getTimeInMillis() ); + return type.cast( new Date( value.getTimeInMillis() ) ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterArrayJavaType.java index 1f75125b1db2..551ff813ac9b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterArrayJavaType.java @@ -37,6 +37,11 @@ public boolean isInstance(Object value) { return value instanceof Character[]; } + @Override + public Character[] cast(Object value) { + return (Character[]) value; + } + @Override public String toString(Character[] value) { return new String( unwrapChars( value ) ); @@ -71,29 +76,28 @@ public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) { : descriptor; } - @SuppressWarnings("unchecked") @Override public X unwrap(Character[] value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Character[].class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) new String( unwrapChars( value ) ); + return type.cast( new String( unwrapChars( value ) ) ); } if ( NClob.class.isAssignableFrom( type ) ) { - return (X) options.getLobCreator().createNClob( new String( unwrapChars( value ) ) ); + return type.cast( options.getLobCreator().createNClob( new String( unwrapChars( value ) ) ) ); } if ( Clob.class.isAssignableFrom( type ) ) { - return (X) options.getLobCreator().createClob( new String( unwrapChars( value ) ) ); + return type.cast( options.getLobCreator().createClob( new String( unwrapChars( value ) ) ) ); } if ( Reader.class.isAssignableFrom( type ) ) { - return (X) new StringReader( new String( unwrapChars( value ) ) ); + return type.cast( new StringReader( new String( unwrapChars( value ) ) ) ); } if ( CharacterStream.class.isAssignableFrom( type ) ) { - return (X) new CharacterStreamImpl( new String( unwrapChars( value ) ) ); + return type.cast( new CharacterStreamImpl( new String( unwrapChars( value ) ) ) ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterJavaType.java index fe16e90592cc..817e8fca31bd 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterJavaType.java @@ -45,20 +45,24 @@ public boolean isInstance(Object value) { return value instanceof Character; } - @SuppressWarnings("unchecked") + @Override + public Character cast(Object value) { + return (Character) value; + } + @Override public X unwrap(Character value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Character.class.isAssignableFrom( type ) || type == Object.class ) { - return (X) value; + return type.cast( value ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) value.toString(); + return type.cast( value.toString() ); } if ( Number.class.isAssignableFrom( type ) ) { - return (X) Short.valueOf( (short) value.charValue() ); + return type.cast( (short) value.charValue() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ClassJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ClassJavaType.java index 02c0e203681a..90754167e741 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ClassJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ClassJavaType.java @@ -26,6 +26,11 @@ public boolean isInstance(Object value) { return value instanceof Class; } + @Override + public Class cast(Object value) { + return (Class) value; + } + @Override public boolean useObjectEqualsHashCode() { return true; @@ -51,16 +56,15 @@ public Class fromString(CharSequence string) { } @Override - @SuppressWarnings("unchecked") public X unwrap(Class value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Class.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) toString( value ); + return type.cast( toString( value ) ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ClobJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ClobJavaType.java index 398d7ee68491..2ff3bd8fb2ec 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ClobJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ClobJavaType.java @@ -52,6 +52,11 @@ public boolean isInstance(Object value) { return value instanceof Clob; } + @Override + public Clob cast(Object value) { + return (Clob) value; + } + @Override public String extractLoggableRepresentation(Clob value) { return value == null ? "null" : "{clob}"; @@ -81,7 +86,6 @@ public Clob getReplacement(Clob original, Clob target, SharedSessionContractImpl .mergeClob( original, target, session ); } - @SuppressWarnings("unchecked") public X unwrap(final Clob value, Class type, WrapperOptions options) { if ( value == null ) { return null; @@ -89,36 +93,36 @@ public X unwrap(final Clob value, Class type, WrapperOptions options) { try { if ( Clob.class.isAssignableFrom( type ) ) { - return (X) options.getLobCreator().toJdbcClob( value ); + return type.cast( options.getLobCreator().toJdbcClob( value ) ); } else if ( String.class.isAssignableFrom( type ) ) { if (value instanceof ClobImplementer clobImplementer) { // if the incoming Clob is a wrapper, just grab the string from its CharacterStream - return (X) clobImplementer.getUnderlyingStream().asString(); + return type.cast( clobImplementer.getUnderlyingStream().asString() ); } else { // otherwise extract the bytes from the stream manually - return (X) extractString( value.getCharacterStream() ); + return type.cast( extractString( value.getCharacterStream() ) ); } } else if ( Reader.class.isAssignableFrom( type ) ) { if (value instanceof ClobImplementer clobImplementer) { // if the incoming NClob is a wrapper, just pass along its BinaryStream - return (X) clobImplementer.getUnderlyingStream().asReader(); + return type.cast( clobImplementer.getUnderlyingStream().asReader() ); } else { // otherwise we need to build a CharacterStream... - return (X) value.getCharacterStream(); + return type.cast( value.getCharacterStream() ); } } else if ( CharacterStream.class.isAssignableFrom( type ) ) { if (value instanceof ClobImplementer clobImplementer) { // if the incoming Clob is a wrapper, just pass along its CharacterStream - return (X) clobImplementer.getUnderlyingStream(); + return type.cast( clobImplementer.getUnderlyingStream() ); } else { // otherwise we need to build a CharacterStream... - return (X) value.getCharacterStream(); + return type.cast( value.getCharacterStream() ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CurrencyJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CurrencyJavaType.java index a2fa030de8fb..9799b675ea1d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CurrencyJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CurrencyJavaType.java @@ -27,6 +27,11 @@ public boolean isInstance(Object value) { return value instanceof Currency; } + @Override + public Currency cast(Object value) { + return (Currency) value; + } + @Override public boolean useObjectEqualsHashCode() { return true; @@ -42,16 +47,15 @@ public Currency fromString(CharSequence string) { return Currency.getInstance( string.toString() ); } - @SuppressWarnings("unchecked") public X unwrap(Currency value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Currency.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) value.getCurrencyCode(); + return type.cast( value.getCurrencyCode() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaType.java index 430a8664a5f8..bed568b2643b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaType.java @@ -48,6 +48,11 @@ public boolean isInstance(Object value) { return value instanceof Date; } + @Override + public Date cast(Object value) { + return (Date) value; + } + @Override public TemporalType getPrecision() { return TemporalType.TIMESTAMP; @@ -114,7 +119,6 @@ public int extractHashCode(Date value) { return CalendarJavaType.INSTANCE.extractHashCode( calendar ); } - @SuppressWarnings("unchecked") @Override public X unwrap(Date value, Class type, WrapperOptions options) { if ( value == null ) { @@ -124,30 +128,30 @@ public X unwrap(Date value, Class type, WrapperOptions options) { final java.sql.Date rtn = value instanceof java.sql.Date ? ( java.sql.Date ) value : new java.sql.Date( value.getTime() ); - return (X) rtn; + return type.cast( rtn ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { final java.sql.Time rtn = value instanceof java.sql.Time ? ( java.sql.Time ) value : new java.sql.Time( value.getTime() % 86_400_000 ); - return (X) rtn; + return type.cast( rtn ); } if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) { final java.sql.Timestamp rtn = value instanceof Timestamp ? ( java.sql.Timestamp ) value : new java.sql.Timestamp( value.getTime() ); - return (X) rtn; + return type.cast( rtn ); } if ( Date.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( Calendar.class.isAssignableFrom( type ) ) { final GregorianCalendar cal = new GregorianCalendar(); cal.setTimeInMillis( value.getTime() ); - return (X) cal; + return type.cast( cal ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( value.getTime() ); + return type.cast( value.getTime() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoubleJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoubleJavaType.java index 3bf60f6c2497..a4cfcd16d679 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoubleJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoubleJavaType.java @@ -53,38 +53,42 @@ public boolean isInstance(Object value) { return value instanceof Double; } - @SuppressWarnings("unchecked") + @Override + public Double cast(Object value) { + return (Double) value; + } + @Override public X unwrap(Double value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Double.class.isAssignableFrom( type ) || type == Object.class ) { - return (X) value; + return type.cast( value ); } if ( Float.class.isAssignableFrom( type ) ) { - return (X) Float.valueOf( value.floatValue() ); + return type.cast( value.floatValue() ); } if ( Byte.class.isAssignableFrom( type ) ) { - return (X) Byte.valueOf( value.byteValue() ); + return type.cast( value.byteValue() ); } if ( Short.class.isAssignableFrom( type ) ) { - return (X) Short.valueOf( value.shortValue() ); + return type.cast( value.shortValue() ); } if ( Integer.class.isAssignableFrom( type ) ) { - return (X) Integer.valueOf( value.intValue() ); + return type.cast( value.intValue() ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( value.longValue() ); + return type.cast( value.longValue() ); } if ( BigInteger.class.isAssignableFrom( type ) ) { - return (X) BigInteger.valueOf( value.longValue() ); + return type.cast( BigInteger.valueOf( value.longValue() ) ); } if ( BigDecimal.class.isAssignableFrom( type ) ) { - return (X) BigDecimal.valueOf( value ); + return type.cast( BigDecimal.valueOf( value ) ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) value.toString(); + return type.cast( value.toString() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoublePrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoublePrimitiveArrayJavaType.java index 0ed6cc8f997f..10218ee8a963 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoublePrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoublePrimitiveArrayJavaType.java @@ -41,6 +41,11 @@ public boolean isInstance(Object value) { return value instanceof double[]; } + @Override + public double[] cast(Object value) { + return (double[]) value; + } + @Override public String extractLoggableRepresentation(double[] value) { return value == null ? super.extractLoggableRepresentation( null ) : Arrays.toString( value ); @@ -106,7 +111,7 @@ public X unwrap(double[] value, Class type, WrapperOptions options) { } if ( type.isInstance( value ) ) { - return (X) value; + return type.cast( value ); } else if ( Object[].class.isAssignableFrom( type ) ) { final Class preferredJavaTypeClass = type.getComponentType(); @@ -114,16 +119,15 @@ else if ( Object[].class.isAssignableFrom( type ) ) { for ( int i = 0; i < value.length; i++ ) { unwrapped[i] = getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ); } - return (X) unwrapped; + return type.cast( unwrapped ); } else if ( type == byte[].class ) { // byte[] can only be requested if the value should be serialized - return (X) SerializationHelper.serialize( value ); + return type.cast( SerializationHelper.serialize( value ) ); } else if ( type == BinaryStream.class ) { // BinaryStream can only be requested if the value should be serialized - //noinspection unchecked - return (X) new ArrayBackedBinaryStream( SerializationHelper.serialize( value ) ); + return type.cast( new ArrayBackedBinaryStream( SerializationHelper.serialize( value ) ) ); } else if ( type.isArray() ) { final Class preferredJavaTypeClass = type.getComponentType(); @@ -131,7 +135,7 @@ else if ( type.isArray() ) { for ( int i = 0; i < value.length; i++ ) { Array.set( unwrapped, i, getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ) ); } - return (X) unwrapped; + return type.cast( unwrapped ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DurationJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DurationJavaType.java index fa26767f4f6f..5412aa4e194b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DurationJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DurationJavaType.java @@ -48,6 +48,11 @@ public boolean isInstance(Object value) { return value instanceof Duration; } + @Override + public Duration cast(Object value) { + return (Duration) value; + } + @Override public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) { return context.getTypeConfiguration() @@ -88,28 +93,27 @@ public Duration fromString(CharSequence string) { } @Override - @SuppressWarnings("unchecked") public X unwrap(Duration duration, Class type, WrapperOptions options) { if ( duration == null ) { return null; } if ( Duration.class.isAssignableFrom( type ) ) { - return (X) duration; + return type.cast( duration ); } if ( BigDecimal.class.isAssignableFrom( type ) ) { - return (X) new BigDecimal( duration.getSeconds() ) + return type.cast( new BigDecimal( duration.getSeconds() ) .movePointRight( 9 ) - .add( new BigDecimal( duration.getNano() ) ); + .add( new BigDecimal( duration.getNano() ) ) ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) duration.toString(); + return type.cast( duration.toString() ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( duration.toNanos() ); + return type.cast( duration.toNanos() ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java index 6f8edb9dfe94..4e33a9875fb8 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java @@ -96,24 +96,23 @@ public T fromString(CharSequence string) { } @Override - @SuppressWarnings("unchecked") public X unwrap(T value, Class type, WrapperOptions options) { if ( String.class.equals( type ) ) { - return (X) toName( value ); + return type.cast( toName( value ) ); } else if ( Long.class.equals( type ) ) { - return (X) toLong( value ); + return type.cast( toLong( value ) ); } else if ( Integer.class.equals( type ) ) { - return (X) toInteger( value ); + return type.cast( toInteger( value ) ); } else if ( Short.class.equals( type ) ) { - return (X) toShort( value ); + return type.cast( toShort( value ) ); } else if ( Byte.class.equals( type ) ) { - return (X) toByte( value ); + return type.cast( toByte( value ) ); } - return (X) value; + return type.cast( value ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatJavaType.java index 4a6c6e9e8f5d..66ed69088b7d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatJavaType.java @@ -52,38 +52,42 @@ public boolean isInstance(Object value) { return value instanceof Float; } - @SuppressWarnings("unchecked") + @Override + public Float cast(Object value) { + return (Float) value; + } + @Override public X unwrap(Float value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Float.class.isAssignableFrom( type ) || type == Object.class ) { - return (X) value; + return type.cast( value ); } if ( Double.class.isAssignableFrom( type ) ) { - return (X) Double.valueOf( value.doubleValue() ); + return type.cast( value.doubleValue() ); } if ( Byte.class.isAssignableFrom( type ) ) { - return (X) Byte.valueOf( value.byteValue() ); + return type.cast( value.byteValue() ); } if ( Short.class.isAssignableFrom( type ) ) { - return (X) Short.valueOf( value.shortValue() ); + return type.cast( value.shortValue() ); } if ( Integer.class.isAssignableFrom( type ) ) { - return (X) Integer.valueOf( value.intValue() ); + return type.cast( value.intValue() ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( value.longValue() ); + return type.cast( value.longValue() ); } if ( BigInteger.class.isAssignableFrom( type ) ) { - return (X) BigInteger.valueOf( value.longValue() ); + return type.cast( BigInteger.valueOf( value.longValue() ) ); } if ( BigDecimal.class.isAssignableFrom( type ) ) { - return (X) BigDecimal.valueOf( value ); + return type.cast( BigDecimal.valueOf( value ) ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) value.toString(); + return type.cast( value.toString() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatPrimitiveArrayJavaType.java index 25f431b6a114..bd67839519c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatPrimitiveArrayJavaType.java @@ -41,6 +41,11 @@ public boolean isInstance(Object value) { return value instanceof float[]; } + @Override + public float[] cast(Object value) { + return (float[]) value; + } + @Override public String extractLoggableRepresentation(float[] value) { return value == null ? super.extractLoggableRepresentation( null ) : Arrays.toString( value ); @@ -106,7 +111,7 @@ public X unwrap(float[] value, Class type, WrapperOptions options) { } if ( type.isInstance( value ) ) { - return (X) value; + return type.cast( value ); } else if ( Object[].class.isAssignableFrom( type ) ) { final Class preferredJavaTypeClass = type.getComponentType(); @@ -114,16 +119,15 @@ else if ( Object[].class.isAssignableFrom( type ) ) { for ( int i = 0; i < value.length; i++ ) { unwrapped[i] = getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ); } - return (X) unwrapped; + return type.cast( unwrapped ); } else if ( type == byte[].class ) { // byte[] can only be requested if the value should be serialized - return (X) SerializationHelper.serialize( value ); + return type.cast( SerializationHelper.serialize( value ) ); } else if ( type == BinaryStream.class ) { // BinaryStream can only be requested if the value should be serialized - //noinspection unchecked - return (X) new ArrayBackedBinaryStream( SerializationHelper.serialize( value ) ); + return type.cast( new ArrayBackedBinaryStream( SerializationHelper.serialize( value ) ) ); } else if ( type.isArray() ) { final Class preferredJavaTypeClass = type.getComponentType(); @@ -131,7 +135,7 @@ else if ( type.isArray() ) { for ( int i = 0; i < value.length; i++ ) { Array.set( unwrapped, i, getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ) ); } - return (X) unwrapped; + return type.cast( unwrapped ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InetAddressJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InetAddressJavaType.java index 1d0d56a15d4c..1d742aa2cfd5 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InetAddressJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InetAddressJavaType.java @@ -51,20 +51,19 @@ public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) { return indicators.getJdbcType( SqlTypes.INET ); } - @SuppressWarnings("unchecked") @Override public X unwrap(InetAddress value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( InetAddress.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( byte[].class.isAssignableFrom( type ) ) { - return (X) value.getAddress(); + return type.cast( value.getAddress() ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) value.getHostAddress(); + return type.cast( value.getHostAddress() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InstantJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InstantJavaType.java index 5b78c6fa8e6f..7a8b7b46406e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InstantJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InstantJavaType.java @@ -47,6 +47,11 @@ public boolean isInstance(Object value) { return value instanceof Instant; } + @Override + public Instant cast(Object value) { + return (Instant) value; + } + @Override public TemporalType getPrecision() { return TemporalType.TIMESTAMP; @@ -88,22 +93,21 @@ public Instant fromString(CharSequence string) { } @Override - @SuppressWarnings("unchecked") public X unwrap(Instant instant, Class type, WrapperOptions options) { if ( instant == null ) { return null; } if ( Instant.class.isAssignableFrom( type ) ) { - return (X) instant; + return type.cast( instant ); } if ( OffsetDateTime.class.isAssignableFrom( type ) ) { - return (X) instant.atOffset( ZoneOffset.UTC ); + return type.cast( instant.atOffset( ZoneOffset.UTC ) ); } if ( Calendar.class.isAssignableFrom( type ) ) { - return (X) GregorianCalendar.from( instant.atZone( ZoneOffset.UTC ) ); + return type.cast( GregorianCalendar.from( instant.atZone( ZoneOffset.UTC ) ) ); } if ( Timestamp.class.isAssignableFrom( type ) ) { @@ -119,27 +123,27 @@ public X unwrap(Instant instant, Class type, WrapperOptions options) { */ final ZonedDateTime zonedDateTime = instant.atZone( ZoneId.systemDefault() ); if ( zonedDateTime.getYear() < 1905 ) { - return (X) Timestamp.valueOf( zonedDateTime.toLocalDateTime() ); + return type.cast( Timestamp.valueOf( zonedDateTime.toLocalDateTime() ) ); } else { - return (X) Timestamp.from( instant ); + return type.cast( Timestamp.from( instant ) ); } } if ( java.sql.Date.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Date( instant.toEpochMilli() ); + return type.cast( new java.sql.Date( instant.toEpochMilli() ) ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Time( instant.toEpochMilli() % 86_400_000 ); + return type.cast( new java.sql.Time( instant.toEpochMilli() % 86_400_000 ) ); } if ( Date.class.isAssignableFrom( type ) ) { - return (X) Date.from( instant ); + return type.cast( Date.from( instant ) ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( instant.toEpochMilli() ); + return type.cast( instant.toEpochMilli() ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerJavaType.java index cd83479a604b..a38d4827a3d1 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerJavaType.java @@ -49,38 +49,42 @@ public boolean isInstance(Object value) { return value instanceof Integer; } - @SuppressWarnings("unchecked") + @Override + public Integer cast(Object value) { + return (Integer) value; + } + @Override public X unwrap(Integer value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Integer.class.isAssignableFrom( type ) || type == Object.class ) { - return (X) value; + return type.cast( value ); } if ( Byte.class.isAssignableFrom( type ) ) { - return (X) Byte.valueOf( value.byteValue() ); + return type.cast( value.byteValue() ); } if ( Short.class.isAssignableFrom( type ) ) { - return (X) Short.valueOf( value.shortValue() ); + return type.cast( value.shortValue() ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( value.longValue() ); + return type.cast( value.longValue() ); } if ( Double.class.isAssignableFrom( type ) ) { - return (X) Double.valueOf( value.doubleValue() ); + return type.cast( value.doubleValue() ); } if ( Float.class.isAssignableFrom( type ) ) { - return (X) Float.valueOf( value.floatValue() ); + return type.cast( value.floatValue() ); } if ( BigInteger.class.isAssignableFrom( type ) ) { - return (X) BigInteger.valueOf( value ); + return type.cast( BigInteger.valueOf( value ) ); } if ( BigDecimal.class.isAssignableFrom( type ) ) { - return (X) BigDecimal.valueOf( value ); + return type.cast( BigDecimal.valueOf( value ) ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) value.toString(); + return type.cast( value.toString() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerPrimitiveArrayJavaType.java index 703e12cf1fbd..5bc19094ea44 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerPrimitiveArrayJavaType.java @@ -41,6 +41,11 @@ public boolean isInstance(Object value) { return value instanceof int[]; } + @Override + public int[] cast(Object value) { + return (int[]) value; + } + @Override public String extractLoggableRepresentation(int[] value) { return value == null ? super.extractLoggableRepresentation( null ) : Arrays.toString( value ); @@ -106,7 +111,7 @@ public X unwrap(int[] value, Class type, WrapperOptions options) { } if ( type.isInstance( value ) ) { - return (X) value; + return type.cast( value ); } else if ( Object[].class.isAssignableFrom( type ) ) { final Class preferredJavaTypeClass = type.getComponentType(); @@ -114,16 +119,15 @@ else if ( Object[].class.isAssignableFrom( type ) ) { for ( int i = 0; i < value.length; i++ ) { unwrapped[i] = getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ); } - return (X) unwrapped; + return type.cast( unwrapped ); } else if ( type == byte[].class ) { // byte[] can only be requested if the value should be serialized - return (X) SerializationHelper.serialize( value ); + return type.cast( SerializationHelper.serialize( value ) ); } else if ( type == BinaryStream.class ) { // BinaryStream can only be requested if the value should be serialized - //noinspection unchecked - return (X) new ArrayBackedBinaryStream( SerializationHelper.serialize( value ) ); + return type.cast( new ArrayBackedBinaryStream( SerializationHelper.serialize( value ) ) ); } else if ( type.isArray() ) { final Class preferredJavaTypeClass = type.getComponentType(); @@ -131,7 +135,7 @@ else if ( type.isArray() ) { for ( int i = 0; i < value.length; i++ ) { Array.set( unwrapped, i, getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ) ); } - return (X) unwrapped; + return type.cast( unwrapped ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java index be7453a46d61..06f7f626be40 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java @@ -105,6 +105,10 @@ default boolean isInstance(Object value) { return getJavaTypeClass().isInstance( value ); } + default T cast(Object value) { + return getJavaTypeClass().cast( value ); + } + /** * Retrieve the {@linkplain MutabilityPlan mutability plan} for this Java type. */ @@ -113,12 +117,11 @@ default MutabilityPlan getMutabilityPlan() { } default T getReplacement(T original, T target, SharedSessionContractImplementor session) { - if ( !getMutabilityPlan().isMutable() || target != null && areEqual( original, target ) ) { - return original; - } - else { - return getMutabilityPlan().deepCopy( original ); - } + final var mutabilityPlan = getMutabilityPlan(); + return !mutabilityPlan.isMutable() + || target != null && areEqual( original, target ) + ? original + : mutabilityPlan.deepCopy( original ); } /** @@ -316,6 +319,25 @@ interface CoercionContext { TypeConfiguration getTypeConfiguration(); } + /** + * Coerce the given value to this type, if possible. + * The default implementation defined her simply + * performs an unchecked cast. Subclasses may override + * to perform meaningful coercion. + * + * @apiNote This operation is currently unsound. It + * should throw {@link CoercionException} when coercion + * fails, or its return value should be changed to + * {@link Object}. However, both of those changes had + * too much impact for now. + * + * @param value The value to coerce + * @param coercionContext The coercion context + * @return The coerced value, or the given value + * if no coercion was possible + * @param The type of the value + */ + @Incubating default T coerce(X value, CoercionContext coercionContext) { //noinspection unchecked return (T) value; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java index 17d55e90340e..bdfb6c23e8ba 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java @@ -74,6 +74,11 @@ public boolean isInstance(Object value) { && !( value instanceof java.sql.Time ); } + @Override + public Date cast(Object value) { + return (Date) value; + } + @Override public boolean areEqual(Date one, Date another) { if ( one == another ) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java index f5dc8d21ea55..48bc52f289e2 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java @@ -74,6 +74,11 @@ public boolean isInstance(Object value) { && !( value instanceof java.sql.Date ); } + @Override + public Date cast(Object value) { + return (Date) value; + } + @Override public int extractHashCode(Date value) { final var calendar = Calendar.getInstance(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java index e18fbc917e1e..2cde56adea3f 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java @@ -75,6 +75,11 @@ public boolean isInstance(Object value) { return value instanceof Date; } + @Override + public Date cast(Object value) { + return (Date) value; + } + @Override public boolean areEqual(Date one, Date another) { if ( one == another ) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateJavaType.java index 949d2e4d940d..5d040c8ffee6 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateJavaType.java @@ -43,6 +43,11 @@ public boolean isInstance(Object value) { return value instanceof LocalDate; } + @Override + public LocalDate cast(Object value) { + return (LocalDate) value; + } + @Override public TemporalType getPrecision() { return TemporalType.DATE; @@ -77,18 +82,17 @@ public LocalDate fromString(CharSequence string) { } @Override - @SuppressWarnings("unchecked") public X unwrap(LocalDate value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( LocalDate.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( java.sql.Date.class.isAssignableFrom( type ) ) { - return (X) java.sql.Date.valueOf( value ); + return type.cast( java.sql.Date.valueOf( value ) ); } final LocalDateTime localDateTime = value.atStartOfDay(); @@ -99,23 +103,23 @@ public X unwrap(LocalDate value, Class type, WrapperOptions options) { // but on top of being more complex than the line below, it won't always work. // Timestamp.from() assumes the number of milliseconds since the epoch means the // same thing in Timestamp and Instant, but it doesn't, in particular before 1900. - return (X) Timestamp.valueOf( localDateTime ); + return type.cast( Timestamp.valueOf( localDateTime ) ); } final var zonedDateTime = localDateTime.atZone( ZoneId.systemDefault() ); if ( Calendar.class.isAssignableFrom( type ) ) { - return (X) GregorianCalendar.from( zonedDateTime ); + return type.cast( GregorianCalendar.from( zonedDateTime ) ); } final var instant = zonedDateTime.toInstant(); if ( Date.class.equals( type ) ) { - return (X) Date.from( instant ); + return type.cast( Date.from( instant ) ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( instant.toEpochMilli() ); + return type.cast( instant.toEpochMilli() ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateTimeJavaType.java index 426903e455c3..d9291581c7c8 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateTimeJavaType.java @@ -45,6 +45,11 @@ public boolean isInstance(Object value) { return value instanceof LocalDateTime; } + @Override + public LocalDateTime cast(Object value) { + return (LocalDateTime) value; + } + @Override public TemporalType getPrecision() { return TemporalType.TIMESTAMP; @@ -78,14 +83,13 @@ public LocalDateTime fromString(CharSequence string) { } @Override - @SuppressWarnings("unchecked") public X unwrap(LocalDateTime value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( LocalDateTime.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( Timestamp.class.isAssignableFrom( type ) ) { @@ -94,31 +98,31 @@ public X unwrap(LocalDateTime value, Class type, WrapperOptions options) // but on top of being more complex than the line below, it won't always work. // Timestamp.from() assumes the number of milliseconds since the epoch means the // same thing in Timestamp and Instant, but it doesn't, in particular before 1900. - return (X) Timestamp.valueOf( value ); + return type.cast( Timestamp.valueOf( value ) ); } if ( java.sql.Date.class.isAssignableFrom( type ) ) { final var instant = value.atZone( ZoneId.systemDefault() ).toInstant(); - return (X) java.sql.Date.from( instant ); + return type.cast( java.sql.Date.from( instant ) ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { final var instant = value.atZone( ZoneId.systemDefault() ).toInstant(); - return (X) java.sql.Time.from( instant ); + return type.cast( java.sql.Time.from( instant ) ); } if ( Date.class.isAssignableFrom( type ) ) { final var instant = value.atZone( ZoneId.systemDefault() ).toInstant(); - return (X) Date.from( instant ); + return type.cast( Date.from( instant ) ); } if ( Calendar.class.isAssignableFrom( type ) ) { - return (X) GregorianCalendar.from( value.atZone( ZoneId.systemDefault() ) ); + return type.cast( GregorianCalendar.from( value.atZone( ZoneId.systemDefault() ) ) ); } if ( Long.class.isAssignableFrom( type ) ) { final var instant = value.atZone( ZoneId.systemDefault() ).toInstant(); - return (X) Long.valueOf( instant.toEpochMilli() ); + return type.cast( instant.toEpochMilli() ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalTimeJavaType.java index ac7a498cba6d..160b4c3c0a07 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalTimeJavaType.java @@ -49,6 +49,11 @@ public boolean isInstance(Object value) { return value instanceof LocalTime; } + @Override + public LocalTime cast(Object value) { + return (LocalTime) value; + } + @Override public TemporalType getPrecision() { return TemporalType.TIME; @@ -83,23 +88,22 @@ public LocalTime fromString(CharSequence string) { } @Override - @SuppressWarnings("unchecked") public X unwrap(LocalTime value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( LocalTime.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( Time.class.isAssignableFrom( type ) ) { final var time = Time.valueOf( value ); final int nanos = value.getNano(); return nanos == 0 - ? (X) time + ? type.cast( time ) // Preserve milliseconds, which java.sql.Time supports - : (X) new Time( time.getTime() + roundToPrecision( nanos, 3 ) / 1000000 ); + : type.cast( new Time( time.getTime() + roundToPrecision( nanos, 3 ) / 1000000 ) ); } // Oracle documentation says to set the Date to January 1, 1970 when convert from @@ -111,21 +115,21 @@ public X unwrap(LocalTime value, Class type, WrapperOptions options) { .atZone( ZoneId.systemDefault() ); if ( Calendar.class.isAssignableFrom( type ) ) { - return (X) GregorianCalendar.from( zonedDateTime ); + return type.cast( GregorianCalendar.from( zonedDateTime ) ); } final var instant = zonedDateTime.toInstant(); if ( Timestamp.class.isAssignableFrom( type ) ) { - return (X) Timestamp.from( instant ); + return type.cast( Timestamp.from( instant ) ); } if ( Date.class.equals( type ) ) { - return (X) Date.from( instant ); + return type.cast( Date.from( instant ) ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( instant.toEpochMilli() ); + return type.cast( instant.toEpochMilli() ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocaleJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocaleJavaType.java index 3ab84ac054ca..4222987435b6 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocaleJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocaleJavaType.java @@ -37,6 +37,11 @@ public boolean isInstance(Object value) { return value instanceof Locale; } + @Override + public Locale cast(Object value) { + return (Locale) value; + } + @Override public boolean useObjectEqualsHashCode() { return true; @@ -181,16 +186,15 @@ private void handleExtension(char[] chars, int start, int length, Locale.Builder } } - @SuppressWarnings("unchecked") public X unwrap(Locale value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Locale.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) (options.useLanguageTagForLocale() ? value.toLanguageTag() : value.toString()); + return type.cast( (options.useLanguageTagForLocale() ? value.toLanguageTag() : value.toString()) ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongJavaType.java index b44b0c871672..f8950f859f69 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongJavaType.java @@ -49,38 +49,42 @@ public boolean isInstance(Object value) { return value instanceof Long; } - @SuppressWarnings("unchecked") + @Override + public Long cast(Object value) { + return (Long) value; + } + @Override public X unwrap(Long value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Long.class.isAssignableFrom( type ) || type == Object.class ) { - return (X) value; + return type.cast( value ); } if ( Byte.class.isAssignableFrom( type ) ) { - return (X) Byte.valueOf( value.byteValue() ); + return type.cast( value.byteValue() ); } if ( Short.class.isAssignableFrom( type ) ) { - return (X) Short.valueOf( value.shortValue() ); + return type.cast( value.shortValue() ); } if ( Integer.class.isAssignableFrom( type ) ) { - return (X) Integer.valueOf( value.intValue() ); + return type.cast( value.intValue() ); } if ( Double.class.isAssignableFrom( type ) ) { - return (X) Double.valueOf( value.doubleValue() ); + return type.cast( value.doubleValue() ); } if ( Float.class.isAssignableFrom( type ) ) { - return (X) Float.valueOf( value.floatValue() ); + return type.cast( value.floatValue() ); } if ( BigInteger.class.isAssignableFrom( type ) ) { - return (X) BigInteger.valueOf( value ); + return type.cast( BigInteger.valueOf( value ) ); } if ( BigDecimal.class.isAssignableFrom( type ) ) { - return (X) BigDecimal.valueOf( value ); + return type.cast( BigDecimal.valueOf( value ) ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) value.toString(); + return type.cast( value.toString() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongPrimitiveArrayJavaType.java index 9ba2fb465034..9a158499fd82 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongPrimitiveArrayJavaType.java @@ -41,6 +41,11 @@ public boolean isInstance(Object value) { return value instanceof long[]; } + @Override + public long[] cast(Object value) { + return (long[]) value; + } + @Override public String extractLoggableRepresentation(long[] value) { return value == null ? super.extractLoggableRepresentation( null ) : Arrays.toString( value ); @@ -106,7 +111,7 @@ public X unwrap(long[] value, Class type, WrapperOptions options) { } if ( type.isInstance( value ) ) { - return (X) value; + return type.cast( value ); } else if ( Object[].class.isAssignableFrom( type ) ) { final Class preferredJavaTypeClass = type.getComponentType(); @@ -114,16 +119,15 @@ else if ( Object[].class.isAssignableFrom( type ) ) { for ( int i = 0; i < value.length; i++ ) { unwrapped[i] = getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ); } - return (X) unwrapped; + return type.cast( unwrapped ); } else if ( type == byte[].class ) { // byte[] can only be requested if the value should be serialized - return (X) SerializationHelper.serialize( value ); + return type.cast( SerializationHelper.serialize( value ) ); } else if ( type == BinaryStream.class ) { // BinaryStream can only be requested if the value should be serialized - //noinspection unchecked - return (X) new ArrayBackedBinaryStream( SerializationHelper.serialize( value ) ); + return type.cast( new ArrayBackedBinaryStream( SerializationHelper.serialize( value ) ) ); } else if ( type.isArray() ) { final Class preferredJavaTypeClass = type.getComponentType(); @@ -131,7 +135,7 @@ else if ( type.isArray() ) { for ( int i = 0; i < value.length; i++ ) { Array.set( unwrapped, i, getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ) ); } - return (X) unwrapped; + return type.cast( unwrapped ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/MutableMutabilityPlan.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/MutableMutabilityPlan.java index 43505f65a807..ff826c2595ef 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/MutableMutabilityPlan.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/MutableMutabilityPlan.java @@ -15,7 +15,7 @@ */ public abstract class MutableMutabilityPlan implements MutabilityPlan { - public static final MutableMutabilityPlan INSTANCE = new MutableMutabilityPlan() { + public static final MutableMutabilityPlan INSTANCE = new MutableMutabilityPlan<>() { @Override protected Object deepCopyNotNull(Object value) { return value; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/NClobJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/NClobJavaType.java index cfff735f39c5..8b8a5d012036 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/NClobJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/NClobJavaType.java @@ -61,6 +61,11 @@ public boolean isInstance(Object value) { return value instanceof NClob; } + @Override + public NClob cast(Object value) { + return (NClob) value; + } + @Override public String extractLoggableRepresentation(NClob value) { return value == null ? "null" : "{nclob}"; @@ -90,7 +95,6 @@ public NClob getReplacement(NClob original, NClob target, SharedSessionContractI .mergeNClob( original, target, session ); } - @SuppressWarnings("unchecked") public X unwrap(final NClob value, Class type, WrapperOptions options) { if ( value == null ) { return null; @@ -98,36 +102,36 @@ public X unwrap(final NClob value, Class type, WrapperOptions options) { try { if ( NClob.class.isAssignableFrom( type ) ) { - return (X) options.getLobCreator().toJdbcNClob( value ); + return type.cast( options.getLobCreator().toJdbcNClob( value ) ); } else if ( String.class.isAssignableFrom( type ) ) { if (value instanceof NClobImplementer clobImplementer) { // if the incoming Clob is a wrapper, just get the underlying String. - return (X) clobImplementer.getUnderlyingStream().asString(); + return type.cast( clobImplementer.getUnderlyingStream().asString() ); } else { // otherwise we need to extract the String. - return (X) extractString( value.getCharacterStream() ); + return type.cast( extractString( value.getCharacterStream() ) ); } } else if ( Reader.class.isAssignableFrom( type ) ) { if (value instanceof NClobImplementer clobImplementer) { // if the incoming NClob is a wrapper, just pass along its CharacterStream - return (X) clobImplementer.getUnderlyingStream().asReader(); + return type.cast( clobImplementer.getUnderlyingStream().asReader() ); } else { // otherwise we need to build a Reader... - return (X) value.getCharacterStream(); + return type.cast( value.getCharacterStream() ); } } else if ( CharacterStream.class.isAssignableFrom( type ) ) { if (value instanceof NClobImplementer clobImplementer) { // if the incoming NClob is a wrapper, just pass along its CharacterStream - return (X) clobImplementer.getUnderlyingStream(); + return type.cast( clobImplementer.getUnderlyingStream() ); } else { // otherwise we need to build a CharacterStream... - return (X) value.getCharacterStream(); + return type.cast( value.getCharacterStream() ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ObjectArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ObjectArrayJavaType.java index bdf4f8643bdc..12debbcf3249 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ObjectArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ObjectArrayJavaType.java @@ -29,6 +29,11 @@ public boolean isInstance(Object value) { return value instanceof Object[]; } + @Override + public Object[] cast(Object value) { + return (Object[]) value; + } + @Override public String toString(Object[] value) { final StringBuilder sb = new StringBuilder(); @@ -77,14 +82,13 @@ public int extractHashCode(Object[] objects) { return hashCode; } - @SuppressWarnings("unchecked") @Override public X unwrap(Object[] value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Object[].class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ObjectJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ObjectJavaType.java index 885e227a1cad..8daa408337f3 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ObjectJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ObjectJavaType.java @@ -29,10 +29,14 @@ public boolean isInstance(Object value) { return true; } + @Override + public Object cast(Object value) { + return value; + } + @Override public X unwrap(Object value, Class type, WrapperOptions options) { - //noinspection unchecked - return (X) value; + return type.cast( value ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java index 7cbdb112578a..591d57487101 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java @@ -67,6 +67,11 @@ public boolean isInstance(Object value) { return value instanceof OffsetDateTime; } + @Override + public OffsetDateTime cast(Object value) { + return (OffsetDateTime) value; + } + @Override public TemporalType getPrecision() { return TemporalType.TIMESTAMP; @@ -116,26 +121,25 @@ public OffsetDateTime fromEncodedString(CharSequence charSequence, int start, in } @Override - @SuppressWarnings("unchecked") public X unwrap(OffsetDateTime offsetDateTime, Class type, WrapperOptions options) { if ( offsetDateTime == null ) { return null; } if ( OffsetDateTime.class.isAssignableFrom( type ) ) { - return (X) offsetDateTime; + return type.cast( offsetDateTime ); } if ( ZonedDateTime.class.isAssignableFrom( type ) ) { - return (X) offsetDateTime.toZonedDateTime(); + return type.cast( offsetDateTime.toZonedDateTime() ); } if ( Instant.class.isAssignableFrom( type ) ) { - return (X) offsetDateTime.toInstant(); + return type.cast( offsetDateTime.toInstant() ); } if ( Calendar.class.isAssignableFrom( type ) ) { - return (X) GregorianCalendar.from( offsetDateTime.toZonedDateTime() ); + return type.cast( GregorianCalendar.from( offsetDateTime.toZonedDateTime() ) ); } if ( Timestamp.class.isAssignableFrom( type ) ) { @@ -151,30 +155,30 @@ public X unwrap(OffsetDateTime offsetDateTime, Class type, WrapperOptions // - around 1905, both methods are equally valid, so we don't really care which // one is used. if ( offsetDateTime.getYear() < 1905 ) { - return (X) Timestamp.valueOf( + return type.cast( Timestamp.valueOf( offsetDateTime.atZoneSameInstant( ZoneId.systemDefault() ) .toLocalDateTime() - ); + ) ); } else { - return (X) Timestamp.from( offsetDateTime.toInstant() ); + return type.cast( Timestamp.from( offsetDateTime.toInstant() ) ); } } if ( java.sql.Date.class.isAssignableFrom( type ) ) { - return (X) java.sql.Date.from( offsetDateTime.toInstant() ); + return type.cast( java.sql.Date.from( offsetDateTime.toInstant() ) ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return (X) java.sql.Time.from( offsetDateTime.toInstant() ); + return type.cast( java.sql.Time.from( offsetDateTime.toInstant() ) ); } if ( Date.class.isAssignableFrom( type ) ) { - return (X) Date.from( offsetDateTime.toInstant() ); + return type.cast( Date.from( offsetDateTime.toInstant() ) ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( offsetDateTime.toInstant().toEpochMilli() ); + return type.cast( offsetDateTime.toInstant().toEpochMilli() ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaType.java index 0c4ec1a3c9dc..8c58fbf90721 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaType.java @@ -49,6 +49,11 @@ public boolean isInstance(Object value) { return value instanceof OffsetTime; } + @Override + public OffsetTime cast(Object value) { + return (OffsetTime) value; + } + @Override public TemporalType getPrecision() { return TemporalType.TIME; @@ -83,7 +88,6 @@ public OffsetTime fromString(CharSequence string) { } @Override - @SuppressWarnings("unchecked") public X unwrap(OffsetTime offsetTime, Class type, WrapperOptions options) { if ( offsetTime == null ) { return null; @@ -93,15 +97,15 @@ public X unwrap(OffsetTime offsetTime, Class type, WrapperOptions options // (since PS.setObject() doesn't support passing a timezone) if ( OffsetTime.class.isAssignableFrom( type ) ) { - return (X) offsetTime; + return type.cast( offsetTime ); } if ( LocalTime.class.isAssignableFrom( type ) ) { - return (X) offsetTime.withOffsetSameInstant( getCurrentSystemOffset() ).toLocalTime(); + return type.cast( offsetTime.withOffsetSameInstant( getCurrentSystemOffset() ).toLocalTime() ); } if ( OffsetDateTime.class.isAssignableFrom( type ) ) { - return (X) offsetTime.atDate( LocalDate.EPOCH ); + return type.cast( offsetTime.atDate( LocalDate.EPOCH ) ); } // for legacy types, we assume that the JDBC timezone is passed to JDBC @@ -113,9 +117,9 @@ public X unwrap(OffsetTime offsetTime, Class type, WrapperOptions options final var time = Time.valueOf( jdbcOffsetTime.toLocalTime() ); final int nanos = jdbcOffsetTime.getNano(); return nanos == 0 - ? (X) time + ? type.cast( time ) // Preserve milliseconds, which java.sql.Time supports - : (X) new Time( time.getTime() + roundToPrecision( nanos, 3 ) / 1000000 ); + : type.cast( new Time( time.getTime() + roundToPrecision( nanos, 3 ) / 1000000 ) ); } final var jdbcOffsetDateTime = jdbcOffsetTime.atDate( LocalDate.EPOCH ); @@ -126,23 +130,23 @@ public X unwrap(OffsetTime offsetTime, Class type, WrapperOptions options // but this won't always work since Timestamp.from() assumes the number of // milliseconds since the epoch means the same thing in Timestamp and Instant, // but it doesn't, in particular before 1900. - return (X) Timestamp.valueOf( jdbcOffsetDateTime.toLocalDateTime() ); + return type.cast( Timestamp.valueOf( jdbcOffsetDateTime.toLocalDateTime() ) ); } if ( Calendar.class.isAssignableFrom( type ) ) { - return (X) GregorianCalendar.from( jdbcOffsetDateTime.toZonedDateTime() ); + return type.cast( GregorianCalendar.from( jdbcOffsetDateTime.toZonedDateTime() ) ); } // for instants, we assume that the JDBC timezone, if any, is ignored - final Instant instant = offsetTime.atDate( LocalDate.EPOCH ).toInstant(); + final var instant = offsetTime.atDate( LocalDate.EPOCH ).toInstant(); if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( instant.toEpochMilli() ); + return type.cast( instant.toEpochMilli() ); } if ( Date.class.isAssignableFrom( type ) ) { - return (X) Date.from( instant ); + return type.cast( Date.from( instant ) ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveByteArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveByteArrayJavaType.java index d68bec284276..f0b51879ce48 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveByteArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveByteArrayJavaType.java @@ -37,6 +37,11 @@ public boolean isInstance(Object value) { return value instanceof byte[]; } + @Override + public byte[] cast(Object value) { + return (byte[]) value; + } + @Override public boolean areEqual(byte[] one, byte[] another) { return one == another @@ -99,29 +104,28 @@ public byte[] fromString(CharSequence string) { return bytes; } - @SuppressWarnings("unchecked") public X unwrap(byte[] value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( byte[].class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( InputStream.class.isAssignableFrom( type ) ) { - return (X) new ByteArrayInputStream( value ); + return type.cast( new ByteArrayInputStream( value ) ); } if ( BinaryStream.class.isAssignableFrom( type ) ) { - return (X) new ArrayBackedBinaryStream( value ); + return type.cast( new ArrayBackedBinaryStream( value ) ); } if ( Blob.class.isAssignableFrom( type ) ) { - return (X) options.getLobCreator().createBlob( value ); + return type.cast( options.getLobCreator().createBlob( value ) ); } if ( type.isAssignableFrom( Byte[].class ) ) { final Byte[] array = new Byte[value.length]; for ( int i = 0; i < value.length; i++ ) { array[i] = value[i]; } - return (X) array; + return type.cast( array ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveCharacterArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveCharacterArrayJavaType.java index 33ccf0bcf506..dad8386ce0dd 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveCharacterArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveCharacterArrayJavaType.java @@ -40,6 +40,11 @@ public boolean isInstance(Object value) { return value instanceof char[]; } + @Override + public char[] cast(Object value) { + return (char[]) value; + } + @Override public boolean areEqual(char[] one, char[] another) { return one == another @@ -55,28 +60,27 @@ public int extractHashCode(char[] chars) { return hashCode; } - @SuppressWarnings("unchecked") public X unwrap(char[] value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( char[].class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) new String( value ); + return type.cast( new String( value ) ); } if ( NClob.class.isAssignableFrom( type ) ) { - return (X) options.getLobCreator().createNClob( new String( value ) ); + return type.cast( options.getLobCreator().createNClob( new String( value ) ) ); } if ( Clob.class.isAssignableFrom( type ) ) { - return (X) options.getLobCreator().createClob( new String( value ) ); + return type.cast( options.getLobCreator().createClob( new String( value ) ) ); } if ( Reader.class.isAssignableFrom( type ) ) { - return (X) new StringReader( new String( value ) ); + return type.cast( new StringReader( new String( value ) ) ); } if ( CharacterStream.class.isAssignableFrom( type ) ) { - return (X) new CharacterStreamImpl( new String( value ) ); + return type.cast( new CharacterStreamImpl( new String( value ) ) ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/SerializableJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/SerializableJavaType.java index 58bbd22656bb..39544887a8ec 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/SerializableJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/SerializableJavaType.java @@ -53,10 +53,9 @@ public SerializableJavaType(Class type, MutabilityPlan mutabilityPlan) { } private static MutabilityPlan createMutabilityPlan(Class type) { - if ( type.isAnnotationPresent( Immutable.class ) ) { - return ImmutableMutabilityPlan.instance(); - } - return (MutabilityPlan) SerializableMutabilityPlan.INSTANCE; + return type.isAnnotationPresent( Immutable.class ) + ? ImmutableMutabilityPlan.instance() + : (MutabilityPlan) SerializableMutabilityPlan.INSTANCE; } @Override @@ -97,31 +96,29 @@ public int extractHashCode(T value) { return PrimitiveByteArrayJavaType.INSTANCE.extractHashCode( toBytes( value ) ); } - @SuppressWarnings("unchecked") public X unwrap(T value, Class type, WrapperOptions options) { if ( value == null ) { return null; } else if ( type.isInstance( value ) ) { - return (X) value; + return type.cast( value ); } else if ( byte[].class.isAssignableFrom( type ) ) { - return (X) toBytes( value ); + return type.cast( toBytes( value ) ); } else if ( InputStream.class.isAssignableFrom( type ) ) { - return (X) new ByteArrayInputStream( toBytes( value ) ); + return type.cast( new ByteArrayInputStream( toBytes( value ) ) ); } else if ( BinaryStream.class.isAssignableFrom( type ) ) { - return (X) new ArrayBackedBinaryStream( toBytes( value ) ); + return type.cast( new ArrayBackedBinaryStream( toBytes( value ) ) ); } else if ( Blob.class.isAssignableFrom( type ) ) { - return (X) options.getLobCreator().createBlob( toBytes( value ) ); + return type.cast( options.getLobCreator().createBlob( toBytes( value ) ) ); } throw unknownUnwrap( type ); } - @SuppressWarnings("unchecked") public T wrap(X value, WrapperOptions options) { if ( value == null ) { return null; @@ -141,7 +138,7 @@ else if (value instanceof Blob blob) { } } else if ( getJavaTypeClass().isInstance( value ) ) { - return (T) value; + return cast( value ); } throw unknownWrap( value.getClass() ); } @@ -150,8 +147,7 @@ protected byte[] toBytes(T value) { return SerializationHelper.serialize( value ); } - @SuppressWarnings("unchecked") protected T fromBytes(byte[] bytes) { - return (T) SerializationHelper.deserialize( bytes, getJavaTypeClass().getClassLoader() ); + return cast( SerializationHelper.deserialize( bytes, getJavaTypeClass().getClassLoader() ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortJavaType.java index bfcb09054837..ed6ef2f81e7d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortJavaType.java @@ -48,6 +48,11 @@ public boolean isInstance(Object value) { return value instanceof Short; } + @Override + public Short cast(Object value) { + return (Short) value; + } + @Override public boolean isWider(JavaType javaType) { return switch ( javaType.getTypeName() ) { @@ -56,32 +61,31 @@ public boolean isWider(JavaType javaType) { }; } - @SuppressWarnings("unchecked") @Override public X unwrap(Short value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( Short.class.isAssignableFrom( type ) || type == Object.class ) { - return (X) value; + return type.cast( value ); } if ( Byte.class.isAssignableFrom( type ) ) { - return (X) Byte.valueOf( value.byteValue() ); + return type.cast( value.byteValue() ); } if ( Integer.class.isAssignableFrom( type ) ) { - return (X) Integer.valueOf( value.intValue() ); + return type.cast( value.intValue() ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( value.longValue() ); + return type.cast( value.longValue() ); } if ( Double.class.isAssignableFrom( type ) ) { - return (X) Double.valueOf( value.doubleValue() ); + return type.cast( value.doubleValue() ); } if ( Float.class.isAssignableFrom( type ) ) { - return (X) Float.valueOf( value.floatValue() ); + return type.cast( value.floatValue() ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) value.toString(); + return type.cast( value.toString() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortPrimitiveArrayJavaType.java index 37b7cf758aac..cf0c853419c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortPrimitiveArrayJavaType.java @@ -41,6 +41,11 @@ public boolean isInstance(Object value) { return value instanceof short[]; } + @Override + public short[] cast(Object value) { + return (short[]) value; + } + @Override public String extractLoggableRepresentation(short[] value) { return value == null ? super.extractLoggableRepresentation( null ) : Arrays.toString( value ); @@ -106,7 +111,7 @@ public X unwrap(short[] value, Class type, WrapperOptions options) { } if ( type.isInstance( value ) ) { - return (X) value; + return type.cast( value ); } else if ( Object[].class.isAssignableFrom( type ) ) { final Class preferredJavaTypeClass = type.getComponentType(); @@ -114,16 +119,15 @@ else if ( Object[].class.isAssignableFrom( type ) ) { for ( int i = 0; i < value.length; i++ ) { unwrapped[i] = getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ); } - return (X) unwrapped; + return type.cast( unwrapped ); } else if ( type == byte[].class ) { // byte[] can only be requested if the value should be serialized - return (X) SerializationHelper.serialize( value ); + return type.cast( SerializationHelper.serialize( value ) ); } else if ( type == BinaryStream.class ) { // BinaryStream can only be requested if the value should be serialized - //noinspection unchecked - return (X) new ArrayBackedBinaryStream( SerializationHelper.serialize( value ) ); + return type.cast( new ArrayBackedBinaryStream( SerializationHelper.serialize( value ) ) ); } else if ( type.isArray() ) { final Class preferredJavaTypeClass = type.getComponentType(); @@ -131,7 +135,7 @@ else if ( type.isArray() ) { for ( int i = 0; i < value.length; i++ ) { Array.set( unwrapped, i, getElementJavaType().unwrap( value[i], preferredJavaTypeClass, options ) ); } - return (X) unwrapped; + return type.cast( unwrapped ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/StringJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/StringJavaType.java index d3ef4969aefd..55bcd5c45b87 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/StringJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/StringJavaType.java @@ -48,6 +48,11 @@ public boolean isInstance(Object value) { return value instanceof String; } + @Override + public String cast(Object value) { + return (String) value; + } + @Override public JdbcType getRecommendedJdbcType(JdbcTypeIndicators stdIndicators) { final var typeConfiguration = stdIndicators.getTypeConfiguration(); @@ -65,37 +70,36 @@ else if ( stdIndicators.isNationalized() ) { return super.getRecommendedJdbcType( stdIndicators ); } - @SuppressWarnings("unchecked") public X unwrap(String value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( String.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( byte[].class.isAssignableFrom( type ) ) { - return (X) value.getBytes( UTF_8 ); + return type.cast( value.getBytes( UTF_8 ) ); } if ( Reader.class.isAssignableFrom( type ) ) { - return (X) new StringReader( value ); + return type.cast( new StringReader( value ) ); } if ( CharacterStream.class.isAssignableFrom( type ) ) { - return (X) new CharacterStreamImpl( value ); + return type.cast( new CharacterStreamImpl( value ) ); } // Since NClob extends Clob, we need to check if type is an NClob // before checking if type is a Clob. That will ensure that // the correct type is returned. if ( NClob.class.isAssignableFrom( type ) ) { - return (X) options.getLobCreator().createNClob( value ); + return type.cast( options.getLobCreator().createNClob( value ) ); } if ( Clob.class.isAssignableFrom( type ) ) { - return (X) options.getLobCreator().createClob( value ); + return type.cast( options.getLobCreator().createClob( value ) ); } if ( Integer.class.isAssignableFrom( type ) ) { - return (X) (Integer) Integer.parseInt( value ); + return type.cast( Integer.parseInt( value ) ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) (Long) Long.parseLong( value ); + return type.cast( Long.parseLong( value ) ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/TimeZoneJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/TimeZoneJavaType.java index 3dbc3133724f..ca46bab84abe 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/TimeZoneJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/TimeZoneJavaType.java @@ -34,6 +34,11 @@ public boolean isInstance(Object value) { return value instanceof TimeZone; } + @Override + public TimeZone cast(Object value) { + return (TimeZone) value; + } + @Override public boolean useObjectEqualsHashCode() { return true; @@ -47,16 +52,15 @@ public TimeZone fromString(CharSequence string) { return TimeZone.getTimeZone( string.toString() ); } - @SuppressWarnings("unchecked") public X unwrap(TimeZone value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( TimeZone.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) toString( value ); + return type.cast( toString( value ) ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/UUIDJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/UUIDJavaType.java index b8d0462f81b7..49c4c27a7b7d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/UUIDJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/UUIDJavaType.java @@ -32,6 +32,11 @@ public boolean isInstance(Object value) { return value instanceof UUID; } + @Override + public UUID cast(Object value) { + return (UUID) value; + } + @Override public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) { return context.getJdbcType( context.getPreferredSqlTypeCodeForUuid() ); @@ -63,19 +68,18 @@ else if ( jdbcType.isBinary() ) { return super.getDefaultSqlLength( dialect, jdbcType ); } - @SuppressWarnings("unchecked") public X unwrap(UUID value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( UUID.class.isAssignableFrom( type ) ) { - return (X) PassThroughTransformer.INSTANCE.transform( value ); + return type.cast( PassThroughTransformer.INSTANCE.transform( value ) ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) ToStringTransformer.INSTANCE.transform( value ); + return type.cast( ToStringTransformer.INSTANCE.transform( value ) ); } if ( byte[].class.isAssignableFrom( type ) ) { - return (X) ToBytesTransformer.INSTANCE.transform( value ); + return type.cast( ToBytesTransformer.INSTANCE.transform( value ) ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/UrlJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/UrlJavaType.java index c111905a754a..2a20d74d9020 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/UrlJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/UrlJavaType.java @@ -29,6 +29,11 @@ public boolean isInstance(Object value) { return value instanceof URL; } + @Override + public URL cast(Object value) { + return (URL) value; + } + @Override public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) { return context.getJdbcType( SqlTypes.VARCHAR ); @@ -52,16 +57,15 @@ public URL fromString(CharSequence string) { } } - @SuppressWarnings("unchecked") public X unwrap(URL value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( URL.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) toString( value ); + return type.cast( toString( value ) ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/YearJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/YearJavaType.java index 732d6b910d61..806e8e1094a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/YearJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/YearJavaType.java @@ -28,6 +28,11 @@ public boolean isInstance(Object value) { return value instanceof Year; } + @Override + public Year cast(Object value) { + return (Year) value; + } + @Override public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) { return context.getJdbcType( Types.INTEGER ); @@ -48,7 +53,6 @@ public Year fromString(CharSequence string) { return string == null ? null : Year.parse( string, FORMATTER ); } - @SuppressWarnings("unchecked") @Override public X unwrap(Year value, Class type, WrapperOptions options) { if ( value == null ) { @@ -56,19 +60,19 @@ public X unwrap(Year value, Class type, WrapperOptions options) { } if ( type.isInstance( value ) ) { - return (X) value; + return type.cast( value ); } if ( Integer.class.isAssignableFrom( type ) ) { - return (X) Integer.valueOf( value.getValue() ); + return type.cast( value.getValue() ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( value.getValue() ); + return type.cast( (long) value.getValue() ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) toString( value ); + return type.cast( toString( value ) ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZoneIdJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZoneIdJavaType.java index da51b52bf2e9..2fba480a7f6d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZoneIdJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZoneIdJavaType.java @@ -29,6 +29,11 @@ public boolean isInstance(Object value) { return value instanceof ZoneId; } + @Override + public ZoneId cast(Object value) { + return (ZoneId) value; + } + @Override public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) { return indicators.getJdbcType( Types.VARCHAR ); @@ -49,17 +54,16 @@ public ZoneId fromString(CharSequence string) { return string == null ? null : ZoneId.of( string.toString() ); } - @SuppressWarnings("unchecked") @Override public X unwrap(ZoneId value, Class type, WrapperOptions options) { if ( value == null ) { return null; } if ( ZoneId.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) toString( value ); + return type.cast( toString( value ) ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZoneOffsetJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZoneOffsetJavaType.java index ba78dba8a58c..1227e2162e9b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZoneOffsetJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZoneOffsetJavaType.java @@ -37,6 +37,11 @@ public boolean isInstance(Object value) { return value instanceof ZoneOffset; } + @Override + public ZoneOffset cast(Object value) { + return (ZoneOffset) value; + } + @Override public boolean useObjectEqualsHashCode() { return true; @@ -56,19 +61,18 @@ public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) { } @Override - @SuppressWarnings("unchecked") public X unwrap(ZoneOffset value, Class type, WrapperOptions wrapperOptions) { if ( value == null ) { return null; } if ( ZoneOffset.class.isAssignableFrom( type ) ) { - return (X) value; + return type.cast( value ); } if ( String.class.isAssignableFrom( type ) ) { - return (X) toString( value ); + return type.cast( toString( value ) ); } if ( Integer.class.isAssignableFrom( type ) ) { - return (X) Integer.valueOf( value.getTotalSeconds() ); + return type.cast( value.getTotalSeconds() ); } throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZonedDateTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZonedDateTimeJavaType.java index cfd3b950e58d..00e4cbd3166e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZonedDateTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZonedDateTimeJavaType.java @@ -47,6 +47,11 @@ public boolean isInstance(Object value) { return value instanceof ZonedDateTime; } + @Override + public ZonedDateTime cast(Object value) { + return (ZonedDateTime) value; + } + @Override public TemporalType getPrecision() { return TemporalType.TIMESTAMP; @@ -80,26 +85,25 @@ public ZonedDateTime fromString(CharSequence string) { } @Override - @SuppressWarnings("unchecked") public X unwrap(ZonedDateTime zonedDateTime, Class type, WrapperOptions options) { if ( zonedDateTime == null ) { return null; } if ( ZonedDateTime.class.isAssignableFrom( type ) ) { - return (X) zonedDateTime; + return type.cast( zonedDateTime ); } if ( OffsetDateTime.class.isAssignableFrom( type ) ) { - return (X) OffsetDateTime.of( zonedDateTime.toLocalDateTime(), zonedDateTime.getOffset() ); + return type.cast( OffsetDateTime.of( zonedDateTime.toLocalDateTime(), zonedDateTime.getOffset() ) ); } if ( Instant.class.isAssignableFrom( type ) ) { - return (X) zonedDateTime.toInstant(); + return type.cast( zonedDateTime.toInstant() ); } if ( Calendar.class.isAssignableFrom( type ) ) { - return (X) GregorianCalendar.from( zonedDateTime ); + return type.cast( GregorianCalendar.from( zonedDateTime ) ); } if ( Timestamp.class.isAssignableFrom( type ) ) { @@ -115,30 +119,30 @@ public X unwrap(ZonedDateTime zonedDateTime, Class type, WrapperOptions o // - around 1905, both methods are equally valid, so we don't really care which // one is used. if ( zonedDateTime.getYear() < 1905 ) { - return (X) Timestamp.valueOf( + return type.cast( Timestamp.valueOf( zonedDateTime.withZoneSameInstant( ZoneId.systemDefault() ) .toLocalDateTime() - ); + ) ); } else { - return (X) Timestamp.from( zonedDateTime.toInstant() ); + return type.cast( Timestamp.from( zonedDateTime.toInstant() ) ); } } if ( java.sql.Date.class.isAssignableFrom( type ) ) { - return (X) java.sql.Date.from( zonedDateTime.toInstant() ); + return type.cast( java.sql.Date.from( zonedDateTime.toInstant() ) ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return (X) java.sql.Time.from( zonedDateTime.toInstant() ); + return type.cast( java.sql.Time.from( zonedDateTime.toInstant() ) ); } if ( Date.class.isAssignableFrom( type ) ) { - return (X) Date.from( zonedDateTime.toInstant() ); + return type.cast( Date.from( zonedDateTime.toInstant() ) ); } if ( Long.class.isAssignableFrom( type ) ) { - return (X) Long.valueOf( zonedDateTime.toInstant().toEpochMilli() ); + return type.cast( zonedDateTime.toInstant().toEpochMilli() ); } throw unknownUnwrap( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java index c0206a382371..fbc44a99a3c1 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java @@ -355,21 +355,18 @@ public X unwrap(C value, Class type, WrapperOptions options) { } if ( type.isInstance( value ) ) { - //noinspection unchecked - return (X) value; + return type.cast( value ); } else if ( type == byte[].class ) { // byte[] can only be requested if the value should be serialized - return (X) SerializationHelper.serialize( asArrayList( value ) ); + return type.cast( SerializationHelper.serialize( asArrayList( value ) ) ); } else if ( type == BinaryStream.class ) { // BinaryStream can only be requested if the value should be serialized - //noinspection unchecked - return (X) new ArrayBackedBinaryStream( SerializationHelper.serialize( asArrayList( value ) ) ); + return type.cast( new ArrayBackedBinaryStream( SerializationHelper.serialize( asArrayList( value ) ) ) ); } else if ( type == Object[].class ) { - //noinspection unchecked - return (X) value.toArray(); + return type.cast( value.toArray() ); } else if ( Object[].class.isAssignableFrom( type ) ) { final var preferredJavaTypeClass = type.getComponentType(); @@ -379,13 +376,11 @@ else if ( Object[].class.isAssignableFrom( type ) ) { unwrapped[i] = componentJavaType.unwrap( element, preferredJavaTypeClass, options ); i++; } - //noinspection unchecked - return (X) unwrapped; + return type.cast( unwrapped ); } else if ( type.isArray() ) { final var preferredJavaTypeClass = type.getComponentType(); - //noinspection unchecked - final X unwrapped = (X) newInstance( preferredJavaTypeClass, value.size() ); + final X unwrapped = type.cast( newInstance( preferredJavaTypeClass, value.size() ) ); int i = 0; for ( E element : value ) { set( unwrapped, i, componentJavaType.unwrap( element, preferredJavaTypeClass, options ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/CollectionJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/CollectionJavaType.java index 7eba1547090f..06ae24e597ba 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/CollectionJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/CollectionJavaType.java @@ -6,7 +6,6 @@ import java.io.Serializable; import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; import java.util.Map; import java.util.Objects; @@ -55,12 +54,13 @@ public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) { public JavaType createJavaType( ParameterizedType parameterizedType, TypeConfiguration typeConfiguration) { - final Type[] typeArguments = parameterizedType.getActualTypeArguments(); + final var typeArguments = parameterizedType.getActualTypeArguments(); final var registry = typeConfiguration.getJavaTypeRegistry(); return switch ( semantics.getCollectionClassification() ) { case ARRAY -> { final var arrayClass = (Class) parameterizedType.getRawType(); - yield (JavaType) new ArrayJavaType<>( registry.resolveDescriptor( arrayClass.getComponentType() ) ); + yield (JavaType) + new ArrayJavaType<>( registry.resolveDescriptor( arrayClass.getComponentType() ) ); } case BAG, ID_BAG, LIST, SET, SORTED_SET, ORDERED_SET -> new BasicCollectionJavaType( diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/EmbeddableAggregateJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/EmbeddableAggregateJavaType.java index 4e9d0d189978..d01abf5b8c24 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/EmbeddableAggregateJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/EmbeddableAggregateJavaType.java @@ -70,8 +70,7 @@ public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) { @Override public X unwrap(T value, Class type, WrapperOptions options) { if ( type.isAssignableFrom( getJavaTypeClass() ) ) { - //noinspection unchecked - return (X) value; + return type.cast( value ); } throw new UnsupportedOperationException( "Unwrap strategy not known for this Java type: " + getTypeName() @@ -83,13 +82,15 @@ public T wrap(X value, WrapperOptions options) { if ( value == null ) { return null; } - if ( getJavaTypeClass().isInstance( value ) ) { - //noinspection unchecked - return (T) value; + else { + final var javaTypeClass = getJavaTypeClass(); + if ( javaTypeClass.isInstance( value ) ) { + return javaTypeClass.cast( value ); + } + throw new UnsupportedOperationException( + "Wrap strategy not known for this Java type: " + getTypeName() + ); } - throw new UnsupportedOperationException( - "Wrap strategy not known for this Java type: " + getTypeName() - ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/EntityJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/EntityJavaType.java index fa57add4632d..b810d42f178f 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/EntityJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/EntityJavaType.java @@ -58,7 +58,7 @@ public boolean isInstance(Object value) { } } - @Override @SuppressWarnings("unchecked") // safe, we do check + @Override public X unwrap(T value, Class type, WrapperOptions options) { final var id = options.getSessionFactory().getMappingMetamodel() @@ -67,14 +67,15 @@ public X unwrap(T value, Class type, WrapperOptions options) { if ( !type.isInstance( id ) ) { throw new IllegalArgumentException( "Id not an instance of type " + type.getName() ); } - return (X) value; + return type.cast( value ); } - @Override @SuppressWarnings("unchecked") // safe, we do check + @Override public T wrap(X value, WrapperOptions options) { + final var entityClass = getJavaTypeClass(); final var persister = options.getSessionFactory().getMappingMetamodel() - .getEntityDescriptor( getJavaTypeClass() ); + .getEntityDescriptor( entityClass ); final var idType = persister.getIdentifierType().getReturnedClass(); if ( !idType.isInstance( value ) ) { throw new IllegalArgumentException( "Not an instance of id type " + idType.getName() ); @@ -82,7 +83,7 @@ public T wrap(X value, WrapperOptions options) { final var entity = options.getSession() .internalLoad( persister.getEntityName(), value, false, true ); - return (T) entity; + return entityClass.cast( entity ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/FormatMapperBasedJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/FormatMapperBasedJavaType.java index e2dc208d72b7..7f0d208c8bc1 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/FormatMapperBasedJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/FormatMapperBasedJavaType.java @@ -65,13 +65,11 @@ public T fromString(CharSequence string) { @Override public X unwrap(T value, Class type, WrapperOptions options) { if ( type.isAssignableFrom( getJavaTypeClass() ) ) { - //noinspection unchecked - return (X) value; + return type.cast( value ); } else if ( type == String.class ) { - //noinspection unchecked - return (X) getFormatMapper( typeConfiguration ) - .toString( value, this, options ); + return type.cast( getFormatMapper( typeConfiguration ) + .toString( value, this, options ) ); } throw new UnsupportedOperationException( "Unwrap strategy not known for this Java type: " + getTypeName() @@ -80,9 +78,9 @@ else if ( type == String.class ) { @Override public T wrap(X value, WrapperOptions options) { - if ( getJavaTypeClass().isInstance( value ) ) { - //noinspection unchecked - return (T) value; + final var javaTypeClass = getJavaTypeClass(); + if ( javaTypeClass.isInstance( value ) ) { + return javaTypeClass.cast( value ); } else if ( value instanceof String string ) { return getFormatMapper( typeConfiguration ) diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/UnknownBasicJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/UnknownBasicJavaType.java index cd8350352248..a4bf77cb7c21 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/UnknownBasicJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/UnknownBasicJavaType.java @@ -64,8 +64,7 @@ public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) { @Override public X unwrap(T value, Class type, WrapperOptions options) { if ( type.isAssignableFrom( getJavaTypeClass() ) ) { - //noinspection unchecked - return (X) value; + return type.cast( value ); } throw new UnsupportedOperationException( "Unwrap strategy not known for this Java type: " + getTypeName() @@ -74,9 +73,9 @@ public X unwrap(T value, Class type, WrapperOptions options) { @Override public T wrap(X value, WrapperOptions options) { - if ( getJavaTypeClass().isInstance( value ) ) { - //noinspection unchecked - return (T) value; + final var javaTypeClass = getJavaTypeClass(); + if ( javaTypeClass.isInstance( value ) ) { + return javaTypeClass.cast( value ); } throw new UnsupportedOperationException( "Wrap strategy not known for this Java type: " + getTypeName() diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ObjectJdbcType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ObjectJdbcType.java index cc7430aeec3d..c7d726f094c0 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ObjectJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ObjectJdbcType.java @@ -70,7 +70,6 @@ protected void doBind(CallableStatement st, X value, String name, WrapperOptions } @Override - @SuppressWarnings("unchecked") public ValueExtractor getExtractor(JavaType javaType) { if ( Serializable.class.isAssignableFrom( javaType.getJavaTypeClass() ) ) { return VarbinaryJdbcType.INSTANCE.getExtractor( javaType ); @@ -79,17 +78,17 @@ public ValueExtractor getExtractor(JavaType javaType) { return new BasicExtractor<>( javaType, this ) { @Override protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException { - return (X) rs.getObject( paramIndex ); + return javaType.cast( rs.getObject( paramIndex ) ); } @Override protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException { - return (X) statement.getObject( index ); + return javaType.cast( statement.getObject( index ) ); } @Override protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException { - return (X) statement.getObject( name ); + return javaType.cast( statement.getObject( name ) ); } }; } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/StructHelper.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/StructHelper.java index 445a779203df..f3e56499f8cf 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/StructHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/StructHelper.java @@ -302,8 +302,7 @@ private static void injectCastJdbcValue( Object relationalValue) throws SQLException { assert javaType.isInstance( relationalValue ); - //noinspection unchecked - injectJdbcValue( jdbcValues, jdbcIndex, options, jdbcMapping, javaType, (T) relationalValue ); + injectJdbcValue( jdbcValues, jdbcIndex, options, jdbcMapping, javaType, javaType.cast( relationalValue ) ); } private static void injectJdbcValue( diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/StructJdbcType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/StructJdbcType.java index 980a0028c470..59cfcee684f6 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/StructJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/StructJdbcType.java @@ -208,8 +208,7 @@ private X getValue(Object object, WrapperOptions options) throws SQLException { StructHelper.orderJdbcValues( embeddableMappingType, inverseOrderMapping, jdbcValues.clone(), jdbcValues ); } wrapRawJdbcValues( embeddableMappingType, jdbcValues, 0, options ); - //noinspection unchecked - return (X) jdbcValues; + return javaType.cast( jdbcValues ); } assert embeddableMappingType != null && embeddableMappingType.getJavaType() == getJavaType(); final StructAttributeValues attributeValues = getAttributeValues( @@ -218,8 +217,7 @@ private X getValue(Object object, WrapperOptions options) throws SQLException { jdbcValues, options ); - //noinspection unchecked - return (X) instantiate( embeddableMappingType, attributeValues ); + return javaType.cast( instantiate( embeddableMappingType, attributeValues ) ); } }; } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlArrayJdbcType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlArrayJdbcType.java index 006718721ca9..ad66399bb35d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlArrayJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlArrayJdbcType.java @@ -64,8 +64,7 @@ protected X fromString(String string, JavaType javaType, WrapperOptions o options.getSession().getJdbcCoordinator().getLogicalConnection().getPhysicalConnection() .createSQLXML(); sqlxml.setString( string ); - //noinspection unchecked - return (X) sqlxml; + return javaType.cast( sqlxml ); } return XmlHelper.arrayFromString( javaType, this, string, options ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlJdbcType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlJdbcType.java index ac139bfcaf54..1aa971d38cdd 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlJdbcType.java @@ -94,11 +94,11 @@ protected X fromString(String string, JavaType javaType, WrapperOptions o } if ( javaType.getJavaType() == SQLXML.class ) { final SQLXML sqlxml = - options.getSession().getJdbcCoordinator().getLogicalConnection().getPhysicalConnection() + options.getSession().getJdbcCoordinator() + .getLogicalConnection().getPhysicalConnection() .createSQLXML(); sqlxml.setString( string ); - //noinspection unchecked - return (X) sqlxml; + return javaType.cast( sqlxml ); } return options.getXmlFormatMapper().fromString( string, javaType, options ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/spi/BasicJdbcLiteralFormatter.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/spi/BasicJdbcLiteralFormatter.java index 038e86c56289..c1677f9078fb 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/spi/BasicJdbcLiteralFormatter.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/spi/BasicJdbcLiteralFormatter.java @@ -18,27 +18,24 @@ public BasicJdbcLiteralFormatter(JavaType javaType) { super( javaType ); } - @SuppressWarnings("unchecked") protected X unwrap(Object value, Class unwrapType, WrapperOptions options) { assert value != null; // for performance reasons, avoid conversions if we can if ( unwrapType.isInstance( value ) ) { - return (X) value; + return unwrapType.cast( value ); } else { - final JavaType javaType = getJavaType(); - if ( !javaType.isInstance( value ) ) { - final T coerced = javaType.coerce( value, options::getTypeConfiguration ); - if ( unwrapType.isInstance( coerced ) ) { - return (X) coerced; - } - else { - return javaType.unwrap( coerced, unwrapType, options ); - } + final var javaType = getJavaType(); + if ( javaType.isInstance( value ) ) { + final T castValue = javaType.cast( value ); + return javaType.unwrap( castValue, unwrapType, options ); } else { - return javaType.unwrap( (T) value, unwrapType, options ); + final T coerced = javaType.coerce( value, options::getTypeConfiguration ); + return unwrapType.isInstance( coerced ) + ? unwrapType.cast( coerced ) + : javaType.unwrap( coerced, unwrapType, options ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/internal/CompositeUserTypeJavaTypeWrapper.java b/hibernate-core/src/main/java/org/hibernate/type/internal/CompositeUserTypeJavaTypeWrapper.java index d7454355bbfb..bc61a9cec25d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/internal/CompositeUserTypeJavaTypeWrapper.java +++ b/hibernate-core/src/main/java/org/hibernate/type/internal/CompositeUserTypeJavaTypeWrapper.java @@ -102,15 +102,12 @@ public J fromString(CharSequence string) { @Override public X unwrap(J value, Class type, WrapperOptions options) { assert value == null || userType.returnedClass().isInstance( value ); - - //noinspection unchecked - return (X) value; + return type.cast( value ); } @Override public J wrap(X value, WrapperOptions options) { // assert value == null || userType.returnedClass().isInstance( value ); - //noinspection unchecked return (J) value; } diff --git a/hibernate-core/src/main/java/org/hibernate/type/internal/UserTypeJavaTypeWrapper.java b/hibernate-core/src/main/java/org/hibernate/type/internal/UserTypeJavaTypeWrapper.java index 7bc589fb4fdd..3dcdd99f22bb 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/internal/UserTypeJavaTypeWrapper.java +++ b/hibernate-core/src/main/java/org/hibernate/type/internal/UserTypeJavaTypeWrapper.java @@ -15,7 +15,6 @@ import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.java.BasicJavaType; import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan; -import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.java.MutabilityPlanExposer; import org.hibernate.type.descriptor.jdbc.JdbcType; @@ -134,22 +133,20 @@ public X unwrap(J value, Class type, WrapperOptions options) { private X unwrap(J value, Class type, BasicValueConverter converter, WrapperOptions options) { if ( value != null && !type.isInstance( value ) && converter != null ) { final Object relationalValue = customType.convertToRelationalValue( value ); - final JavaType relationalJavaType = converter.getRelationalJavaType(); - assert relationalJavaType.isInstance( relationalValue ); - //noinspection unchecked - return relationalJavaType.unwrap( (R) relationalValue, type, options ); + final var relationalJavaType = converter.getRelationalJavaType(); + final var castValue = relationalJavaType.cast( relationalValue ); + return relationalJavaType.unwrap( castValue, type, options ); } else { - //noinspection unchecked - return (X) value; + return type.cast( value ); } } @Override public J wrap(X value, WrapperOptions options) { - final BasicValueConverter converter = customType.getValueConverter(); + final var converter = customType.getValueConverter(); if ( value != null && !userType.returnedClass().isInstance( value ) && converter != null ) { - final JavaType domainJavaType = converter.getDomainJavaType(); + final var domainJavaType = converter.getDomainJavaType(); final Object domainValue = customType.convertToDomainValue( value ); assert domainJavaType.isInstance( value ); return domainJavaType.wrap( domainValue, options ); From 69b7b8b705694c04b21809c1c43089970ce01672 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 6 Dec 2025 23:45:00 +0100 Subject: [PATCH 02/10] more use of Class.cast() instead of unchecked casts and fallout also a bunch of 'var's --- .../hibernate/boot/internal/MetadataImpl.java | 10 +- .../jaxb/hbm/transform/HbmXmlTransformer.java | 5 +- .../internal/ConverterDescriptors.java | 9 +- .../boot/model/internal/AnnotationHelper.java | 9 +- .../model/internal/NamedGraphCreatorJpa.java | 55 +++--- .../internal/GlobalRegistrationsImpl.java | 3 +- .../BytecodeEnhancementMetadataPojoImpl.java | 6 +- .../bytebuddy/BasicProxyFactoryImpl.java | 50 ++--- .../internal/DefaultCacheKeysFactory.java | 26 ++- .../cache/internal/DisabledCaching.java | 3 +- .../cache/internal/EnabledCaching.java | 5 +- .../AbstractPostgreSQLStructJdbcType.java | 122 +++++-------- .../internal/ConfigurationServiceImpl.java | 51 +++--- .../internal/EntityEntryExtraStateHolder.java | 6 +- .../engine/internal/EntityEntryImpl.java | 6 +- .../internal/ConnectionProviderInitiator.java | 4 +- .../DataSourceConnectionProvider.java | 5 +- .../DriverManagerConnectionProvider.java | 3 +- .../UserSuppliedConnectionProviderImpl.java | 3 +- ...asedMultiTenantConnectionProviderImpl.java | 7 +- ...AbstractMultiTenantConnectionProvider.java | 7 +- .../engine/spi/SessionLazyDelegator.java | 12 +- .../DefaultReplicateEventListener.java | 12 +- .../internal/EventListenerRegistryImpl.java | 5 +- .../org/hibernate/graph/EntityGraphs.java | 4 +- .../hibernate/graph/internal/GraphImpl.java | 2 +- .../org/hibernate/internal/SessionImpl.java | 17 +- .../util/type/PrimitiveWrapperHelper.java | 12 ++ .../EntityManagerFactoryBuilderImpl.java | 4 +- .../org/hibernate/jpa/spi/JpaCompliance.java | 2 +- .../internal/AbstractMultiIdEntityLoader.java | 30 +-- .../internal/IdentifierLoadAccessImpl.java | 5 +- .../metamodel/mapping/ValueMapping.java | 3 +- .../NonAggregatedIdentifierMappingImpl.java | 13 +- .../domain/internal/JpaMetamodelImpl.java | 171 +++++++++--------- .../internal/ProjectionSpecificationImpl.java | 6 +- .../spi/AbstractCommonQueryContract.java | 1 + .../sqm/internal/SqmCriteriaNodeBuilder.java | 75 ++++---- .../sqm/sql/BaseSqmToSqlAstConverter.java | 6 +- .../sqm/tree/domain/AbstractSqmFrom.java | 87 +++++---- .../tree/expression/SqmJsonNullBehavior.java | 7 +- .../tree/select/AbstractSqmSelectQuery.java | 28 +-- .../internal/AbstractJdbcOperationQuery.java | 3 +- .../results/internal/StandardRowReader.java | 98 +++++----- .../sql/results/internal/TupleImpl.java | 23 +-- .../java/org/hibernate/usertype/UserType.java | 5 +- .../java/org/hibernate/orm/test/EnumType.java | 3 +- 47 files changed, 510 insertions(+), 519 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java index 22389a3b558a..ec02695b70aa 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java @@ -501,13 +501,13 @@ private void appendListeners( EventType eventType) { final var eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType ); for ( String listenerImpl : splitAtCommas( listeners ) ) { - @SuppressWarnings("unchecked") - T listener = (T) instantiate( listenerImpl, classLoaderService ); - if ( !eventType.baseListenerInterface().isInstance( listener ) ) { + final var listener = instantiate( listenerImpl, classLoaderService ); + final var baseListenerInterface = eventType.baseListenerInterface(); + if ( !baseListenerInterface.isInstance( listener ) ) { throw new HibernateException( "Event listener '" + listenerImpl - + "' must implement '" + eventType.baseListenerInterface().getName() + "'"); + + "' must implement '" + baseListenerInterface.getName() + "'"); } - eventListenerGroup.appendListener( listener ); + eventListenerGroup.appendListener( baseListenerInterface.cast( listener ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/jaxb/hbm/transform/HbmXmlTransformer.java b/hibernate-core/src/main/java/org/hibernate/boot/jaxb/hbm/transform/HbmXmlTransformer.java index 559b94e6a50e..94bc743ca848 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/jaxb/hbm/transform/HbmXmlTransformer.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/jaxb/hbm/transform/HbmXmlTransformer.java @@ -713,7 +713,7 @@ private void transferImports() { if ( !hbmImports.isEmpty() ) { final var ormRoot = mappingXmlBinding.getRoot(); for ( var hbmImport : hbmImports ) { - final JaxbHqlImportImpl ormImport = new JaxbHqlImportImpl(); + final var ormImport = new JaxbHqlImportImpl(); ormRoot.getHqlImports().add( ormImport ); ormImport.setClazz( hbmImport.getClazz() ); ormImport.setRename( hbmImport.getRename() ); @@ -890,7 +890,8 @@ private static JaxbNamedHqlQueryImpl transformNamedQuery(JaxbHbmNamedQueryType h query.setQuery( qryString ); } else { - @SuppressWarnings("unchecked") final var element = (JAXBElement) content; + @SuppressWarnings("unchecked") + final var element = (JAXBElement) content; final var hbmQueryParam = element.getValue(); final var queryParam = new JaxbQueryParamTypeImpl(); query.getQueryParam().add( queryParam ); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/ConverterDescriptors.java b/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/ConverterDescriptors.java index 047635bd09d5..4c1900dd9274 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/ConverterDescriptors.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/ConverterDescriptors.java @@ -30,8 +30,7 @@ public static ConverterDescriptor of( Class> converterClass, Boolean autoApply, boolean overrideable, ClassmateContext classmateContext) { @SuppressWarnings("unchecked") // work around weird fussiness in wildcard capture - final Class> converterType = - (Class>) converterClass; + final var converterType = (Class>) converterClass; return new ClassBasedConverterDescriptor<>( converterType, autoApply, classmateContext, overrideable ); } @@ -39,8 +38,7 @@ public static ConverterDescriptor of( Class> converterClass, ClassmateContext classmateContext) { @SuppressWarnings("unchecked") // work around weird fussiness in wildcard capture - final Class> converterType = - (Class>) converterClass; + final var converterType = (Class>) converterClass; return new ClassBasedConverterDescriptor<>( converterType, null, classmateContext, false ); } @@ -48,8 +46,7 @@ public static ConverterDescriptor of( Class> converterType, ResolvedType domainTypeToMatch, ResolvedType relationalType, boolean autoApply) { @SuppressWarnings("unchecked") // work around weird fussiness in wildcard capture - final Class> converterClass = - (Class>) converterType; + final var converterClass = (Class>) converterType; return new ConverterDescriptorImpl<>( converterClass, domainTypeToMatch, relationalType, autoApply ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationHelper.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationHelper.java index b6cf53a618be..10f300375a5f 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationHelper.java @@ -41,7 +41,7 @@ public static HashMap extractParameterMap(Parameter[] parameters public static JdbcMapping resolveUserType(Class> userTypeClass, MetadataBuildingContext context) { final var bootstrapContext = context.getBootstrapContext(); - final UserType userType = + final var userType = context.getBuildingOptions().isAllowExtensionsInCdi() ? bootstrapContext.getManagedBeanRegistry().getBean( userTypeClass ).getBeanInstance() : FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( userTypeClass ); @@ -74,7 +74,7 @@ public static JdbcMapping resolveAttributeConverter( public static BasicType resolveBasicType(Class type, MetadataBuildingContext context) { final var typeConfiguration = context.getBootstrapContext().getTypeConfiguration(); - final JavaType jtd = typeConfiguration.getJavaTypeRegistry().findDescriptor( type ); + final var jtd = typeConfiguration.getJavaTypeRegistry().findDescriptor( type ); if ( jtd != null ) { final JdbcType jdbcType = jtd.getRecommendedJdbcType( new JdbcTypeIndicators() { @@ -132,7 +132,7 @@ private static JavaType getJavaType( Class> javaTypeClass, MetadataBuildingContext context, TypeConfiguration typeConfiguration) { - final JavaType registeredJtd = + final var registeredJtd = typeConfiguration.getJavaTypeRegistry() .findDescriptor( javaTypeClass ); if ( registeredJtd != null ) { @@ -143,8 +143,7 @@ else if ( !context.getBuildingOptions().isAllowExtensionsInCdi() ) { } else { return context.getBootstrapContext().getManagedBeanRegistry() - .getBean( javaTypeClass ) - .getBeanInstance(); + .getBean( javaTypeClass ).getBeanInstance(); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/NamedGraphCreatorJpa.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/NamedGraphCreatorJpa.java index 5e51ff06fcbb..9aebd53de1c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/NamedGraphCreatorJpa.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/NamedGraphCreatorJpa.java @@ -6,7 +6,6 @@ import jakarta.persistence.NamedAttributeNode; import jakarta.persistence.NamedEntityGraph; -import jakarta.persistence.NamedSubgraph; import org.hibernate.AnnotationException; import org.hibernate.boot.model.NamedGraphCreator; import org.hibernate.graph.internal.RootGraphImpl; @@ -41,23 +40,23 @@ public RootGraphImplementor createEntityGraph( Function, EntityDomainType> entityDomainClassResolver, Function> entityDomainNameResolver) { //noinspection unchecked - final EntityDomainType rootEntityType = - (EntityDomainType) entityDomainNameResolver.apply( jpaEntityName ); - final RootGraphImplementor entityGraph = + final var rootEntityType = + (EntityDomainType) + entityDomainNameResolver.apply( jpaEntityName ); + final var entityGraph = createRootGraph( name, rootEntityType, annotation.includeAllAttributes() ); - if ( annotation.subclassSubgraphs() != null ) { - for ( NamedSubgraph subclassSubgraph : annotation.subclassSubgraphs() ) { - final Class subgraphType = subclassSubgraph.type(); - final Class graphJavaType = entityGraph.getGraphedType().getJavaType(); + final var subclassSubgraphs = annotation.subclassSubgraphs(); + if ( subclassSubgraphs != null ) { + for ( var subclassSubgraph : subclassSubgraphs ) { + final var subgraphType = subclassSubgraph.type(); + final var graphJavaType = entityGraph.getGraphedType().getJavaType(); if ( !graphJavaType.isAssignableFrom( subgraphType ) ) { throw new AnnotationException( "Named subgraph type '" + subgraphType.getName() - + "' is not a subtype of the graph type '" + graphJavaType.getName() + "'" ); + + "' is not a subtype of the graph type '" + graphJavaType.getName() + "'" ); } - @SuppressWarnings("unchecked") // Safe, because we just checked - final Class subtype = (Class) subgraphType; - final GraphImplementor subgraph = entityGraph.addTreatedSubgraph( subtype ); - applyNamedAttributeNodes( subclassSubgraph.attributeNodes(), annotation, subgraph ); + applyNamedAttributeNodes( subclassSubgraph.attributeNodes(), annotation, + entityGraph.addTreatedSubgraph( subgraphType.asSubclass( graphJavaType ) ) ); } } @@ -72,7 +71,7 @@ private static RootGraphImplementor createRootGraph( String name, EntityDomainType rootEntityType, boolean includeAllAttributes) { - final RootGraphImpl entityGraph = new RootGraphImpl<>( name, rootEntityType ); + final var entityGraph = new RootGraphImpl<>( name, rootEntityType ); if ( includeAllAttributes ) { for ( var attribute : rootEntityType.getAttributes() ) { entityGraph.addAttributeNodes( attribute ); @@ -85,7 +84,7 @@ private void applyNamedAttributeNodes( NamedAttributeNode[] namedAttributeNodes, NamedEntityGraph namedEntityGraph, GraphImplementor graphNode) { - for ( NamedAttributeNode namedAttributeNode : namedAttributeNodes ) { + for ( var namedAttributeNode : namedAttributeNodes ) { final var attributeNode = (AttributeNodeImplementor) graphNode.addAttributeNode( namedAttributeNode.value() ); @@ -105,7 +104,7 @@ private void applyNamedSubgraphs( String subgraphName, AttributeNodeImplementor attributeNode, boolean isKeySubGraph) { - for ( NamedSubgraph namedSubgraph : namedEntityGraph.subgraphs() ) { + for ( var namedSubgraph : namedEntityGraph.subgraphs() ) { if ( subgraphName.equals( namedSubgraph.name() ) ) { applyNamedAttributeNodes( namedSubgraph.attributeNodes(), namedEntityGraph, createSubgraph( attributeNode, isKeySubGraph, namedSubgraph.type() ) ); @@ -128,27 +127,27 @@ private static SubGraphImplementor createSubgraph( private static SubGraphImplementor makeAttributeNodeValueSubgraph( AttributeNodeImplementor attributeNode, Class subgraphType) { - final Class attributeValueType = - attributeNode.getAttributeDescriptor().getValueGraphType().getJavaType(); + final var attributeValueType = + attributeNode.getAttributeDescriptor() + .getValueGraphType().getJavaType(); if ( !attributeValueType.isAssignableFrom( subgraphType ) ) { throw new AnnotationException( "Named subgraph type '" + subgraphType.getName() - + "' is not a subtype of the value type '" + attributeValueType.getName() + "'" ); + + "' is not a subtype of the value type '" + attributeValueType.getName() + "'" ); } - @SuppressWarnings("unchecked") // Safe, because we just checked - final Class castType = (Class) subgraphType; - return attributeNode.addValueSubgraph().addTreatedSubgraph( castType ); + return attributeNode.addValueSubgraph().addTreatedSubgraph( + subgraphType.asSubclass( attributeNode.getValueSubgraph().getClassType() ) ); } private static SubGraphImplementor makeAttributeNodeKeySubgraph( AttributeNodeImplementor attributeNode, Class subgraphType) { - final Class attributeKeyType = - attributeNode.getAttributeDescriptor().getKeyGraphType().getJavaType(); + final var attributeKeyType = + attributeNode.getAttributeDescriptor() + .getKeyGraphType().getJavaType(); if ( !attributeKeyType.isAssignableFrom( subgraphType ) ) { throw new AnnotationException( "Named subgraph type '" + subgraphType.getName() - + "' is not a subtype of the key type '" + attributeKeyType.getName() + "'" ); + + "' is not a subtype of the key type '" + attributeKeyType.getName() + "'" ); } - @SuppressWarnings("unchecked") // Safe, because we just checked - final Class castType = (Class) subgraphType; - return attributeNode.addKeySubgraph().addTreatedSubgraph( castType ); + return attributeNode.addKeySubgraph().addTreatedSubgraph( + subgraphType.asSubclass( attributeNode.getKeySubgraph().getClassType() ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/internal/GlobalRegistrationsImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/models/internal/GlobalRegistrationsImpl.java index 674c4e1a73ec..bb29a06bef95 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/models/internal/GlobalRegistrationsImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/models/internal/GlobalRegistrationsImpl.java @@ -157,8 +157,7 @@ public GlobalRegistrationsImpl(ModelsContext sourceModelContext, BootstrapContex @Override public T as(Class type) { - //noinspection unchecked - return (T) this; + return type.cast( this ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/BytecodeEnhancementMetadataPojoImpl.java b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/BytecodeEnhancementMetadataPojoImpl.java index 10677b67feb1..b793a37648f2 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/BytecodeEnhancementMetadataPojoImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/BytecodeEnhancementMetadataPojoImpl.java @@ -272,7 +272,8 @@ public void injectInterceptor( PersistentAttributeInterceptor interceptor, SharedSessionContractImplementor session) { if ( !enhancedForLazyLoading ) { - throw new NotInstrumentedException( "Entity class [" + entityClass.getName() + "] is not enhanced for lazy loading" ); + throw new NotInstrumentedException( "Entity class '" + entityClass.getName() + + "' is not enhanced for lazy loading" ); } if ( !entityClass.isInstance( entity ) ) { @@ -291,7 +292,8 @@ public void injectInterceptor( @Override public @Nullable BytecodeLazyAttributeInterceptor extractLazyInterceptor(Object entity) throws NotInstrumentedException { if ( !enhancedForLazyLoading ) { - throw new NotInstrumentedException( "Entity class [" + entityClass.getName() + "] is not enhanced for lazy loading" ); + throw new NotInstrumentedException( "Entity class [" + entityClass.getName() + + "] is not enhanced for lazy loading" ); } if ( !entityClass.isInstance( entity ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java index 1c86fd450e63..8b0475ec0754 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java @@ -9,7 +9,6 @@ import net.bytebuddy.description.modifier.Visibility; import org.hibernate.AssertionFailure; import org.hibernate.HibernateException; -import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImplConstants; import org.hibernate.bytecode.spi.BasicProxyFactory; import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes; import org.hibernate.internal.util.collections.ArrayHelper; @@ -17,16 +16,17 @@ import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy; +import static org.hibernate.proxy.ProxyConfiguration.INTERCEPTOR_FIELD_NAME; + public class BasicProxyFactoryImpl implements BasicProxyFactory { - private static final Class[] NO_INTERFACES = ArrayHelper.EMPTY_CLASS_ARRAY; + private static final Class[] NO_INTERFACES = ArrayHelper.EMPTY_CLASS_ARRAY; private static final String PROXY_NAMING_SUFFIX = "HibernateBasicProxy"; - private final Class proxyClass; - private final Constructor proxyClassConstructor; + private final Class proxyClass; + private final Constructor proxyClassConstructor; - @SuppressWarnings({ "unchecked", "rawtypes" }) - public BasicProxyFactoryImpl(final Class superClass, final Class interfaceClass, final ByteBuddyState byteBuddyState) { + public BasicProxyFactoryImpl(final Class superClass, final Class interfaceClass, final ByteBuddyState byteBuddyState) { if ( superClass == null && interfaceClass == null ) { throw new AssertionFailure( "attempting to build proxy without any superclass or interfaces" ); } @@ -35,9 +35,9 @@ public BasicProxyFactoryImpl(final Class superClass, final Class interfaceClass, throw new AssertionFailure( "Ambiguous call: we assume invocation with EITHER a superClass OR an interfaceClass" ); } - final Class superClassOrMainInterface = superClass != null ? superClass : interfaceClass; - final ByteBuddyState.ProxyDefinitionHelpers helpers = byteBuddyState.getProxyDefinitionHelpers(); - final EnhancerImplConstants constants = byteBuddyState.getEnhancerConstants(); + final var superClassOrMainInterface = superClass != null ? superClass : interfaceClass; + final var helpers = byteBuddyState.getProxyDefinitionHelpers(); + final var constants = byteBuddyState.getEnhancerConstants(); final String proxyClassName = superClassOrMainInterface.getName() + "$" + PROXY_NAMING_SUFFIX; this.proxyClass = byteBuddyState.loadBasicProxy( superClassOrMainInterface, proxyClassName, (byteBuddy, namingStrategy) -> @@ -45,11 +45,11 @@ public BasicProxyFactoryImpl(final Class superClass, final Class interfaceClass, .with( namingStrategy ) .subclass( superClass == null ? Object.class : superClass, ConstructorStrategy.Default.DEFAULT_CONSTRUCTOR ) .implement( interfaceClass == null ? NO_INTERFACES : new Class[]{ interfaceClass } ) - .defineField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE ) - .method( byteBuddyState.getProxyDefinitionHelpers().getVirtualNotFinalizerFilter() ) - .intercept( byteBuddyState.getProxyDefinitionHelpers().getDelegateToInterceptorDispatcherMethodDelegation() ) + .defineField( INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE ) + .method( helpers.getVirtualNotFinalizerFilter() ) + .intercept( helpers.getDelegateToInterceptorDispatcherMethodDelegation() ) .implement( constants.INTERFACES_for_ProxyConfiguration ) - .intercept( byteBuddyState.getProxyDefinitionHelpers().getInterceptorFieldAccessor() ) + .intercept( helpers.getInterceptorFieldAccessor() ) ) ); @@ -63,21 +63,25 @@ public BasicProxyFactoryImpl(final Class superClass, final Class interfaceClass, @Override public Object getProxy() { - final PrimeAmongSecondarySupertypes instance; + final var instance = instantiateProxy(); + final var proxyConfiguration = instance.asProxyConfiguration(); + if ( proxyConfiguration == null ) { + throw new HibernateException( "Produced proxy does not correctly implement ProxyConfiguration" ); + } + // Create a dedicated interceptor for the proxy. + // This is required as the interceptor is stateful. + proxyConfiguration.$$_hibernate_set_interceptor( + new PassThroughInterceptor( proxyClass.getName() ) ); + return instance; + } + + private PrimeAmongSecondarySupertypes instantiateProxy() { try { - instance = (PrimeAmongSecondarySupertypes) proxyClassConstructor.newInstance(); + return (PrimeAmongSecondarySupertypes) proxyClassConstructor.newInstance(); } catch (Throwable t) { throw new HibernateException( "Unable to instantiate proxy instance", t ); } - final ProxyConfiguration proxyConfiguration = instance.asProxyConfiguration(); - if ( proxyConfiguration == null ) { - throw new HibernateException( "Produced proxy does not correctly implement ProxyConfiguration" ); - } - // Create a dedicated interceptor for the proxy. This is required as the interceptor is stateful. - final ProxyConfiguration.Interceptor interceptor = new PassThroughInterceptor( proxyClass.getName() ); - proxyConfiguration.$$_hibernate_set_interceptor( interceptor ); - return instance; } public boolean isInstance(Object object) { diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/DefaultCacheKeysFactory.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/DefaultCacheKeysFactory.java index 388812b964de..e9710a217c42 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/internal/DefaultCacheKeysFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/DefaultCacheKeysFactory.java @@ -4,17 +4,17 @@ */ package org.hibernate.cache.internal; -import java.io.Serializable; import org.hibernate.cache.spi.CacheKeysFactory; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.type.BasicType; import org.hibernate.type.Type; /** - * Second level cache providers now have the option to use custom key implementations. + * Second-level cache providers now have the option to use custom key implementations. * This was done as the default key implementation is very generic and is quite * a large object to allocate in large quantities at runtime. * In some extreme cases, for example when the hit ratio is very low, this was making the efficiency @@ -45,20 +45,30 @@ public class DefaultCacheKeysFactory implements CacheKeysFactory { public static Object staticCreateCollectionKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { final Type keyType = persister.getKeyType(); - final Serializable disassembledKey = keyType.disassemble( id, factory ); + final var coercedId = getCoercedId( id, factory, keyType ); + final var disassembledKey = keyType.disassemble( coercedId, factory ); final boolean idIsArray = disassembledKey.getClass().isArray(); + final String role = persister.getRole(); return tenantIdentifier == null && !idIsArray - ? new BasicCacheKeyImplementation( id, disassembledKey, keyType, persister.getRole() ) - : new CacheKeyImplementation( id, disassembledKey, keyType, persister.getRole(), tenantIdentifier ); + ? new BasicCacheKeyImplementation( coercedId, disassembledKey, keyType, role ) + : new CacheKeyImplementation( coercedId, disassembledKey, keyType, role, tenantIdentifier ); } public static Object staticCreateEntityKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { final Type keyType = persister.getIdentifierType(); - final Serializable disassembledKey = keyType.disassemble( id, factory ); + final var coercedId = getCoercedId( id, factory, keyType ); + final var disassembledKey = keyType.disassemble( coercedId, factory ); final boolean idIsArray = disassembledKey.getClass().isArray(); + final String rootEntityName = persister.getRootEntityName(); return tenantIdentifier == null && !idIsArray - ? new BasicCacheKeyImplementation( id, disassembledKey, keyType, persister.getRootEntityName() ) - : new CacheKeyImplementation( id, disassembledKey, keyType, persister.getRootEntityName(), tenantIdentifier ); + ? new BasicCacheKeyImplementation( coercedId, disassembledKey, keyType, rootEntityName ) + : new CacheKeyImplementation( coercedId, disassembledKey, keyType, rootEntityName, tenantIdentifier ); + } + + private static Object getCoercedId(Object id, SessionFactoryImplementor factory, Type keyType) { + return keyType instanceof BasicType basicType + ? basicType.getJavaTypeDescriptor().coerce( id, factory::getTypeConfiguration ) + : id; } public static Object staticCreateNaturalIdKey( diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/DisabledCaching.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/DisabledCaching.java index 8986678a4b13..ade8b582440b 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/internal/DisabledCaching.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/DisabledCaching.java @@ -220,10 +220,9 @@ public void evict(Class cls) { } @Override - @SuppressWarnings("unchecked") public T unwrap(Class type) { if ( type.isAssignableFrom( DisabledCaching.class ) ) { - return (T) this; + return type.cast( this ); } else { throw new PersistenceException( "Hibernate cannot unwrap Cache as '" + type.getName() + "'" ); diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/EnabledCaching.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/EnabledCaching.java index 093e2fc606be..76c233fc60cb 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/internal/EnabledCaching.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/EnabledCaching.java @@ -523,13 +523,12 @@ public void evictRegion(String regionName) { } @Override - @SuppressWarnings("unchecked") public T unwrap(Class type) { if ( type.isAssignableFrom( EnabledCaching.class ) ) { - return (T) this; + return type.cast( this ); } else if ( type.isAssignableFrom( RegionFactory.class ) ) { - return (T) regionFactory; + return type.cast( regionFactory ); } else { throw new PersistenceException( "Hibernate cannot unwrap Cache as '" + type.getName() + "'" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/type/AbstractPostgreSQLStructJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/type/AbstractPostgreSQLStructJdbcType.java index 5a28ee9ef16d..e07a1483242f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/type/AbstractPostgreSQLStructJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/type/AbstractPostgreSQLStructJdbcType.java @@ -4,27 +4,9 @@ */ package org.hibernate.dialect.type; -import java.lang.reflect.Array; -import java.sql.CallableStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.temporal.ChronoField; -import java.time.temporal.TemporalAccessor; -import java.util.ArrayList; -import java.util.TimeZone; - import org.hibernate.internal.util.CharSequenceHelper; import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.JdbcMapping; -import org.hibernate.metamodel.mapping.MappingType; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.ValuedModelPart; import org.hibernate.sql.ast.spi.SqlAppender; @@ -43,13 +25,31 @@ import org.hibernate.type.descriptor.jdbc.StructuredJdbcType; import org.hibernate.type.spi.TypeConfiguration; -import static org.hibernate.type.descriptor.jdbc.StructHelper.getSubPart; -import static org.hibernate.type.descriptor.jdbc.StructHelper.instantiate; +import java.sql.CallableStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalAccessor; +import java.util.ArrayList; +import java.util.TimeZone; + +import static java.lang.reflect.Array.get; +import static java.lang.reflect.Array.getLength; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsLocalTime; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMicros; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMillis; +import static org.hibernate.type.descriptor.jdbc.StructHelper.getSubPart; +import static org.hibernate.type.descriptor.jdbc.StructHelper.instantiate; /** * Implementation for serializing/deserializing an embeddable aggregate to/from the PostgreSQL component format. @@ -189,15 +189,13 @@ protected X fromString(String string, JavaType javaType, WrapperOptions o } assert end == string.length(); if ( returnEmbeddable ) { - final StructAttributeValues attributeValues = getAttributeValues( embeddableMappingType, orderMapping, array, options ); - //noinspection unchecked - return (X) instantiate( embeddableMappingType, attributeValues ); + final var attributeValues = getAttributeValues( embeddableMappingType, orderMapping, array, options ); + return javaType.cast( instantiate( embeddableMappingType, attributeValues ) ); } else if ( inverseOrderMapping != null ) { StructHelper.orderJdbcValues( embeddableMappingType, inverseOrderMapping, array.clone(), array ); } - //noinspection unchecked - return (X) array; + return javaType.cast( array ); } private int deserializeStruct( @@ -336,7 +334,7 @@ private int deserializeStruct( continue; } assert isDoubleQuote( string, i, 1 << quotes ); - final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); + final var jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); switch ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() ) { case SqlTypes.DATE: values[column] = fromRawObject( @@ -450,7 +448,7 @@ private int deserializeStruct( i += expectedQuotes - 1; if ( string.charAt( i + 1 ) == '(' ) { // This could be a nested struct - final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); + final var jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); if ( jdbcMapping.getJdbcType() instanceof AbstractPostgreSQLStructJdbcType structJdbcType ) { final Object[] subValues = new Object[structJdbcType.embeddableMappingType.getJdbcValueCount()]; final int subEnd = structJdbcType.deserializeStruct( @@ -500,7 +498,7 @@ private int deserializeStruct( } else if ( string.charAt( i + 1 ) == '{' ) { // This could be a quoted array - final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); + final var jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); if ( jdbcMapping instanceof BasicPluralType pluralType ) { final ArrayList arrayList = new ArrayList<>(); //noinspection unchecked @@ -543,7 +541,7 @@ else if ( string.charAt( i + 1 ) == '{' ) { values[column] = null; } else { - final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); + final var jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); if ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() == SqlTypes.BOOLEAN ) { values[column] = fromRawObject( jdbcMapping, @@ -579,7 +577,7 @@ else if ( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass().isEnum() values[column] = null; } else { - final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); + final var jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); if ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() == SqlTypes.BOOLEAN ) { values[column] = fromRawObject( jdbcMapping, @@ -610,7 +608,7 @@ else if ( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass().isEnum() break; case '{': if ( !inQuote ) { - final BasicPluralType pluralType = (BasicPluralType) getJdbcValueSelectable( column ).getJdbcMapping(); + final var pluralType = (BasicPluralType) getJdbcValueSelectable( column ).getJdbcMapping(); final ArrayList arrayList = new ArrayList<>(); //noinspection unchecked i = deserializeArray( @@ -645,14 +643,10 @@ private boolean isBinary(int column) { } private static boolean isBinary(JdbcMapping jdbcMapping) { - switch ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() ) { - case SqlTypes.BINARY: - case SqlTypes.VARBINARY: - case SqlTypes.LONGVARBINARY: - case SqlTypes.LONG32VARBINARY: - return true; - } - return false; + return switch ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() ) { + case SqlTypes.BINARY, SqlTypes.VARBINARY, SqlTypes.LONGVARBINARY, SqlTypes.LONG32VARBINARY -> true; + default -> false; + }; } private int deserializeArray( @@ -803,7 +797,7 @@ private int deserializeArray( ); break; default: - if ( escapingSb == null || escapingSb.length() == 0 ) { + if ( escapingSb == null || escapingSb.isEmpty() ) { values.add( fromString( elementType, @@ -1027,19 +1021,6 @@ private static boolean isDoubleQuote(String string, int start, int escapes) { return false; } - private Object fromString( - int selectableIndex, - String string, - int start, - int end) { - return fromString( - getJdbcValueSelectable( selectableIndex ).getJdbcMapping(), - string, - start, - end - ); - } - private static Object fromString(JdbcMapping jdbcMapping, CharSequence charSequence, int start, int end) { return jdbcMapping.getJdbcJavaType().fromEncodedString( charSequence, @@ -1064,22 +1045,19 @@ private Object parseTime(CharSequence subSequence) { } private Object parseTimestamp(CharSequence subSequence, JavaType jdbcJavaType) { - final TemporalAccessor temporalAccessor = LOCAL_DATE_TIME.parse( subSequence ); - final LocalDateTime localDateTime = LocalDateTime.from( temporalAccessor ); - final Timestamp timestamp = Timestamp.valueOf( localDateTime ); + final var temporalAccessor = LOCAL_DATE_TIME.parse( subSequence ); + final var localDateTime = LocalDateTime.from( temporalAccessor ); + final var timestamp = Timestamp.valueOf( localDateTime ); timestamp.setNanos( temporalAccessor.get( ChronoField.NANO_OF_SECOND ) ); return timestamp; } private Object parseTimestampWithTimeZone(CharSequence subSequence, JavaType jdbcJavaType) { - final TemporalAccessor temporalAccessor = LOCAL_DATE_TIME.parse( subSequence ); + final var temporalAccessor = LOCAL_DATE_TIME.parse( subSequence ); if ( temporalAccessor.isSupported( ChronoField.OFFSET_SECONDS ) ) { - if ( jdbcJavaType.getJavaTypeClass() == Instant.class ) { - return Instant.from( temporalAccessor ); - } - else { - return OffsetDateTime.from( temporalAccessor ); - } + return jdbcJavaType.getJavaTypeClass() == Instant.class + ? Instant.from( temporalAccessor ) + : OffsetDateTime.from( temporalAccessor ); } return LocalDateTime.from( temporalAccessor ); } @@ -1129,7 +1107,7 @@ protected String toString(X value, JavaType javaType, WrapperOptions opti if ( value == null ) { return null; } - final StringBuilder sb = new StringBuilder(); + final var sb = new StringBuilder(); serializeStructTo( new PostgreSQLAppender( sb ), value, options ); return sb.toString(); } @@ -1164,10 +1142,10 @@ private void serializeJdbcValuesTo( if ( jdbcValue == null ) { continue; } - final SelectableMapping selectableMapping = orderMapping == null ? + final var selectableMapping = orderMapping == null ? embeddableMappingType.getJdbcValueSelectable( i ) : embeddableMappingType.getJdbcValueSelectable( orderMapping[i] ); - final JdbcMapping jdbcMapping = selectableMapping.getJdbcMapping(); + final var jdbcMapping = selectableMapping.getJdbcMapping(); if ( jdbcMapping.getJdbcType() instanceof AbstractPostgreSQLStructJdbcType structJdbcType ) { appender.quoteStart(); structJdbcType.serializeJdbcValuesTo( @@ -1267,7 +1245,7 @@ private void serializeConvertedBasicTo( break; case SqlTypes.ARRAY: if ( subValue != null ) { - final int length = Array.getLength( subValue ); + final int length = getLength( subValue ); if ( length == 0 ) { appender.append( "{}" ); } @@ -1276,7 +1254,7 @@ private void serializeConvertedBasicTo( final BasicType elementType = ((BasicPluralType) jdbcMapping).getElementType(); appender.quoteStart(); appender.append( '{' ); - Object arrayElement = Array.get( subValue, 0 ); + Object arrayElement = get( subValue, 0 ); if ( arrayElement == null ) { appender.appendNull(); } @@ -1284,7 +1262,7 @@ private void serializeConvertedBasicTo( serializeConvertedBasicTo( appender, options, elementType, arrayElement ); } for ( int i = 1; i < length; i++ ) { - arrayElement = Array.get( subValue, i ); + arrayElement = get( subValue, i ); appender.append( ',' ); if ( arrayElement == null ) { appender.appendNull(); @@ -1301,7 +1279,7 @@ private void serializeConvertedBasicTo( break; case SqlTypes.STRUCT: if ( subValue != null ) { - final AbstractPostgreSQLStructJdbcType structJdbcType = (AbstractPostgreSQLStructJdbcType) jdbcMapping.getJdbcType(); + final var structJdbcType = (AbstractPostgreSQLStructJdbcType) jdbcMapping.getJdbcType(); appender.quoteStart(); structJdbcType.serializeJdbcValuesTo( appender, options, (Object[]) subValue, '(' ); appender.append( ')' ); @@ -1354,7 +1332,7 @@ private int injectAttributeValue( Object[] rawJdbcValues, int jdbcIndex, WrapperOptions options) throws SQLException { - final MappingType mappedType = modelPart.getMappedType(); + final var mappedType = modelPart.getMappedType(); final int jdbcValueCount; final Object rawJdbcValue = rawJdbcValues[jdbcIndex]; if ( mappedType instanceof EmbeddableMappingType embeddableMappingType ) { @@ -1378,7 +1356,7 @@ private int injectAttributeValue( else { assert modelPart.getJdbcTypeCount() == 1; jdbcValueCount = 1; - final JdbcMapping jdbcMapping = modelPart.getSingleJdbcMapping(); + final var jdbcMapping = modelPart.getSingleJdbcMapping(); final Object jdbcValue = jdbcMapping.getJdbcJavaType().wrap( rawJdbcValue, options diff --git a/hibernate-core/src/main/java/org/hibernate/engine/config/internal/ConfigurationServiceImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/config/internal/ConfigurationServiceImpl.java index 005ee176c523..ed0ac5d4fecc 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/config/internal/ConfigurationServiceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/config/internal/ConfigurationServiceImpl.java @@ -66,42 +66,49 @@ public void injectServices(ServiceRegistryImplementor serviceRegistry) { return target !=null ? target : defaultValue; } - @SuppressWarnings("unchecked") public @Nullable T cast(Class expected, @Nullable Object candidate){ - if (candidate == null) { + if ( candidate == null ) { return null; } + else if ( expected.isInstance( candidate ) ) { + return expected.cast( candidate ); + } + else { + final var target = getTargetClass( expected, candidate ); + return target == null ? null : instantiate( expected, target ); - if ( expected.isInstance( candidate ) ) { - return (T) candidate; } + } + + private static @Nullable T instantiate(Class expected, Class target) { + try { + return target.getDeclaredConstructor().newInstance(); + } + catch (Exception e) { + //TODO: should this really be a debug-level + // log instead of a proper error? + CORE_LOGGER.debugf( "Unable to instantiate %s class %s", + expected.getName(), target.getName() ); + return null; + } + } - Class target; - if (candidate instanceof Class) { - target = (Class) candidate; + private @Nullable Class getTargetClass(Class expected, Object candidate) { + if ( candidate instanceof Class candidateClass ) { + return candidateClass.asSubclass( expected ); } else { try { - target = serviceRegistry.requireService( ClassLoaderService.class ) + return serviceRegistry.requireService( ClassLoaderService.class ) .classForName( candidate.toString() ); } - catch ( ClassLoadingException e ) { + catch (ClassLoadingException e) { + //TODO: should this really be a debug-level + // log instead of a proper error? CORE_LOGGER.debugf( "Unable to locate %s implementation class %s", expected.getName(), candidate.toString() ); - target = null; + return null; } } - if ( target != null ) { - try { - return target.newInstance(); - } - catch ( Exception e ) { - CORE_LOGGER.debugf( "Unable to instantiate %s class %s", - expected.getName(), target.getName() ); - } - } - return null; } - - } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryExtraStateHolder.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryExtraStateHolder.java index 6a53f3f79b0d..95ba26e31fff 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryExtraStateHolder.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryExtraStateHolder.java @@ -36,13 +36,13 @@ public void addExtraState(EntityEntryExtraState extraState) { } } - @Override @SuppressWarnings("unchecked") + @Override public T getExtraState(Class extraStateType) { if ( next == null ) { return null; } - if ( extraStateType.isAssignableFrom( next.getClass() ) ) { - return (T) next; + if ( extraStateType.isInstance( next ) ) { + return extraStateType.cast( next ); } else { return next.getExtraState( extraStateType ); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryImpl.java index f32adf748e9b..37fce72bf597 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryImpl.java @@ -548,13 +548,13 @@ public void addExtraState(EntityEntryExtraState extraState) { } } - @Override @SuppressWarnings("unchecked") + @Override public T getExtraState(Class extraStateType) { if ( next == null ) { return null; } - else if ( extraStateType.isAssignableFrom( next.getClass() ) ) { - return (T) next; + else if ( extraStateType.isInstance( next ) ) { + return extraStateType.cast( next ); } else { return next.getExtraState( extraStateType ); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/ConnectionProviderInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/ConnectionProviderInitiator.java index e39abf7d9278..ef0112e9ada2 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/ConnectionProviderInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/ConnectionProviderInitiator.java @@ -116,9 +116,7 @@ private static Class connectionProviderClass(Class throw new ConnectionProviderConfigurationException( "Class '" + providerClass.getName() + "' does not implement 'ConnectionProvider'" ); } - @SuppressWarnings("unchecked") // Safe, we just checked - final var connectionProviderClass = (Class) providerClass; - return connectionProviderClass; + return providerClass.asSubclass( ConnectionProvider.class ); } private ConnectionProvider instantiateNamedConnectionProvider( diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DataSourceConnectionProvider.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DataSourceConnectionProvider.java index 5fb8e27e552e..3d1d60479286 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DataSourceConnectionProvider.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DataSourceConnectionProvider.java @@ -73,13 +73,12 @@ public boolean isUnwrappableAs(Class unwrapType) { } @Override - @SuppressWarnings("unchecked") public T unwrap(Class unwrapType) { if ( unwrapType.isAssignableFrom( DataSourceConnectionProvider.class ) ) { - return (T) this; + return unwrapType.cast( this ); } else if ( unwrapType.isAssignableFrom( DataSource.class) ) { - return (T) getDataSource(); + return unwrapType.cast( getDataSource() ); } else { throw new UnknownUnwrapTypeException( unwrapType ); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProvider.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProvider.java index 3013dd5054d0..600294069c26 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProvider.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProvider.java @@ -322,10 +322,9 @@ public boolean isUnwrappableAs(Class unwrapType) { } @Override - @SuppressWarnings( {"unchecked"}) public T unwrap(Class unwrapType) { if ( unwrapType.isAssignableFrom( DriverManagerConnectionProvider.class ) ) { - return (T) this; + return unwrapType.cast( this ); } else { throw new UnknownUnwrapTypeException( unwrapType ); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/UserSuppliedConnectionProviderImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/UserSuppliedConnectionProviderImpl.java index f85a9144faac..35c79503eba4 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/UserSuppliedConnectionProviderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/UserSuppliedConnectionProviderImpl.java @@ -25,10 +25,9 @@ public boolean isUnwrappableAs(Class unwrapType) { } @Override - @SuppressWarnings( {"unchecked"}) public T unwrap(Class unwrapType) { if ( unwrapType.isAssignableFrom( UserSuppliedConnectionProviderImpl.class ) ) { - return (T) this; + return unwrapType.cast( this ); } else { throw new UnknownUnwrapTypeException( unwrapType ); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/AbstractDataSourceBasedMultiTenantConnectionProviderImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/AbstractDataSourceBasedMultiTenantConnectionProviderImpl.java index e14bafb1729b..0649321fd924 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/AbstractDataSourceBasedMultiTenantConnectionProviderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/AbstractDataSourceBasedMultiTenantConnectionProviderImpl.java @@ -52,13 +52,12 @@ public boolean isUnwrappableAs(Class unwrapType) { } @Override - @SuppressWarnings("unchecked") - public T unwrap(Class unwrapType) { + public X unwrap(Class unwrapType) { if ( unwrapType.isInstance( this ) ) { - return (T) this; + return unwrapType.cast( this ); } else if ( unwrapType.isAssignableFrom( DataSource.class ) ) { - return (T) selectAnyDataSource(); + return unwrapType.cast( selectAnyDataSource() ); } else { throw new UnknownUnwrapTypeException( unwrapType ); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/AbstractMultiTenantConnectionProvider.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/AbstractMultiTenantConnectionProvider.java index 6117ea3e59d0..55e98ec0b8d1 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/AbstractMultiTenantConnectionProvider.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/AbstractMultiTenantConnectionProvider.java @@ -54,13 +54,12 @@ public boolean isUnwrappableAs(Class unwrapType) { } @Override - @SuppressWarnings("unchecked") - public T unwrap(Class unwrapType) { + public X unwrap(Class unwrapType) { if ( unwrapType.isInstance( this ) ) { - return (T) this; + return unwrapType.cast( this ); } else if ( unwrapType.isAssignableFrom( ConnectionProvider.class ) ) { - return (T) getAnyConnectionProvider(); + return unwrapType.cast( getAnyConnectionProvider() ); } else { throw new UnknownUnwrapTypeException( unwrapType ); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionLazyDelegator.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionLazyDelegator.java index 19fbf55a7a03..ca102676a444 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionLazyDelegator.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionLazyDelegator.java @@ -886,17 +886,15 @@ public boolean isJoinedToTransaction() { } @Override - public T unwrap(Class cls) { - if ( cls.isAssignableFrom( Session.class ) ) { - //noinspection unchecked - return (T) this; - } - return this.lazySession.get().unwrap( cls ); + public T unwrap(Class type) { + return type.isAssignableFrom( Session.class ) + ? type.cast( this ) + : lazySession.get().unwrap( type ); } @Override public Object getDelegate() { - return this.lazySession.get().getDelegate(); + return lazySession.get().getDelegate(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultReplicateEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultReplicateEventListener.java index 710c4593eccc..c1db00d2a228 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultReplicateEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultReplicateEventListener.java @@ -114,7 +114,17 @@ else if ( EVENT_LISTENER_LOGGER.isTraceEnabled() ) { private static boolean shouldOverwrite( ReplicationMode replicationMode, Object entityVersion, Object realOldVersion, BasicType versionType) { - return replicationMode.shouldOverwriteCurrentVersion( (T) realOldVersion, (T) entityVersion, versionType ); + return replicationMode.shouldOverwriteCurrentVersion( + castVersion( realOldVersion, versionType ), + castVersion( entityVersion, versionType ), + versionType + ); + } + + private static T castVersion(Object realOldVersion, BasicType versionType) { + return versionType == null + ? null + : versionType.getJavaTypeDescriptor().cast( realOldVersion ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java index 2bda60e2a49b..445ac91b47c8 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java @@ -135,10 +135,9 @@ private T[] resolveListenerInstances(EventType type, Class.. } private T resolveListenerInstance(Class listenerClass) { - @SuppressWarnings("unchecked") - final T listenerInstance = (T) listenerClassToInstanceMap.get( listenerClass ); + final T listenerInstance = listenerClass.cast( listenerClassToInstanceMap.get( listenerClass ) ); if ( listenerInstance == null ) { - T newListenerInstance = instantiateListener( listenerClass ); + final T newListenerInstance = instantiateListener( listenerClass ); listenerClassToInstanceMap.put( listenerClass, newListenerInstance ); return newListenerInstance; } diff --git a/hibernate-core/src/main/java/org/hibernate/graph/EntityGraphs.java b/hibernate-core/src/main/java/org/hibernate/graph/EntityGraphs.java index 9d38c57924e1..9106be1fd9d9 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/EntityGraphs.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/EntityGraphs.java @@ -64,13 +64,13 @@ public static EntityGraph createGraph(EntityType rootType) { * @since 7.0 */ public static EntityGraph> createGraphForDynamicEntity(EntityType rootType) { - final EntityDomainType domainType = (EntityDomainType) rootType; + final var domainType = (EntityDomainType) rootType; if ( domainType.getRepresentationMode() != RepresentationMode.MAP ) { throw new IllegalArgumentException( "Entity '" + domainType.getHibernateEntityName() + "' is not a dynamic entity" ); } @SuppressWarnings("unchecked") //Safe, because we just checked - final EntityDomainType> dynamicEntity = (EntityDomainType>) domainType; + final var dynamicEntity = (EntityDomainType>) domainType; return new RootGraphImpl<>( null, dynamicEntity ); } diff --git a/hibernate-core/src/main/java/org/hibernate/graph/internal/GraphImpl.java b/hibernate-core/src/main/java/org/hibernate/graph/internal/GraphImpl.java index cd40c149e714..b28471f203f8 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/internal/GraphImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/internal/GraphImpl.java @@ -182,7 +182,7 @@ private static void mergeNode( AttributeNodeImplementor node, AttributeNodeImplementor existingNode) { if ( existingNode.getAttributeDescriptor() == node.getAttributeDescriptor() ) { @SuppressWarnings("unchecked") // safe, we just checked - final AttributeNodeImplementor castNode = (AttributeNodeImplementor) node; + final var castNode = (AttributeNodeImplementor) node; existingNode.merge( castNode ); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index 82b2f2e250a7..9f01e1fe356d 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -2789,23 +2789,24 @@ public Collection getManagedEntities(String entityName) { public Collection getManagedEntities(Class entityType) { return persistenceContext.getEntityHoldersByKey().entrySet().stream() .filter( entry -> entry.getKey().getPersister().getMappedClass().equals( entityType ) ) - .map( entry -> (E) entry.getValue().getManagedObject() ) + .map( entry -> entityType.cast( entry.getValue().getManagedObject() ) ) .toList(); } @Override public Collection getManagedEntities(EntityType entityType) { - final String entityName = ( (EntityDomainType) entityType ).getHibernateEntityName(); + final var entityDomainType = (EntityDomainType) entityType; + final String entityName = entityDomainType.getHibernateEntityName(); return persistenceContext.getEntityHoldersByKey().entrySet().stream() .filter( entry -> entry.getKey().getEntityName().equals( entityName ) ) - .map( entry -> (E) entry.getValue().getManagedObject() ) + .map( entry -> entityType.getJavaType().cast( entry.getValue().getManagedObject() ) ) .toList(); } /** - * Used by JDK serialization... + * Used by JDK serialization * - * @param oos The output stream to which we are being written... + * @param oos The output stream to which we are being written * * @throws IOException Indicates a general IO stream exception */ @@ -2824,9 +2825,9 @@ private void writeObject(ObjectOutputStream oos) throws IOException { } /** - * Used by JDK serialization... + * Used by JDK serialization * - * @param ois The input stream from which we are being read... + * @param ois The input stream from which we are being read * * @throws IOException Indicates a general IO stream exception * @throws ClassNotFoundException Indicates a class resolution issue @@ -2846,7 +2847,7 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFound // LoadQueryInfluencers#getEnabledFilters() tries to validate each enabled // filter, which will fail when called before FilterImpl#afterDeserialize( factory ); - // Instead lookup the filter by name and then call FilterImpl#afterDeserialize( factory ). + // Instead, look up the filter by name and then call FilterImpl#afterDeserialize( factory ). for ( String filterName : loadQueryInfluencers.getEnabledFilterNames() ) { ( (FilterImpl) loadQueryInfluencers.getEnabledFilter( filterName ) ) .afterDeserialize( getFactory() ); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/type/PrimitiveWrapperHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/type/PrimitiveWrapperHelper.java index e9c2de5052d0..d2e88c50ea20 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/type/PrimitiveWrapperHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/type/PrimitiveWrapperHelper.java @@ -21,6 +21,18 @@ public interface PrimitiveWrapperDescriptor { Class getWrapperClass(); } + public static X cast(Class type, Object value) { + return type.isPrimitive() + ? getDescriptorByPrimitiveType( type ).getWrapperClass().cast( value ) + : type.cast( value ); + } + + public static boolean isInstance(Class type, Object value) { + return type.isPrimitive() + ? getDescriptorByPrimitiveType( type ).getWrapperClass().isInstance( value ) + : type.isInstance( value ); + } + public static class BooleanDescriptor implements PrimitiveWrapperDescriptor { public static final BooleanDescriptor INSTANCE = new BooleanDescriptor(); diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java index 8d82e0320a57..b05f5da713ed 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java @@ -1515,8 +1515,8 @@ private String exceptionHeader() { @SuppressWarnings("unchecked") private T loadSettingInstance(String settingName, Object settingValue, Class clazz) { final Class instanceClass; - if ( clazz.isAssignableFrom( settingValue.getClass() ) ) { - return (T) settingValue; + if ( clazz.isInstance( settingValue ) ) { + return clazz.cast( settingValue ); } else if ( settingValue instanceof Class ) { instanceClass = (Class) settingValue; diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/spi/JpaCompliance.java b/hibernate-core/src/main/java/org/hibernate/jpa/spi/JpaCompliance.java index 630800df6e7b..af90dae005bc 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/spi/JpaCompliance.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/spi/JpaCompliance.java @@ -123,7 +123,7 @@ public interface JpaCompliance { * {@link jakarta.persistence.EntityManager#find} should be exactly the * expected type, allowing no type coercion. *

- * Historically, Hibernate behaved the same way. Since 6.0 however, + * Historically, Hibernate behaved the same way. Since 6.0, however, * Hibernate has the ability to coerce the passed type to the expected * type. For example, an {@link Integer} may be widened to {@link Long}. * Coercion is performed by calling diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiIdEntityLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiIdEntityLoader.java index 24e8f5f49fbb..a792b296e9cb 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiIdEntityLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiIdEntityLoader.java @@ -20,6 +20,7 @@ import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.sql.ast.SqlAstTranslatorFactory; import org.hibernate.sql.exec.spi.JdbcSelectExecutor; +import org.hibernate.type.descriptor.java.JavaType; import java.util.ArrayList; import java.util.List; @@ -39,11 +40,17 @@ public abstract class AbstractMultiIdEntityLoader implements MultiIdEntityLoa private final EntityMappingType entityDescriptor; private final SessionFactoryImplementor sessionFactory; protected final EntityIdentifierMapping identifierMapping; + private final boolean idCoercionEnabled; public AbstractMultiIdEntityLoader(EntityMappingType entityDescriptor, SessionFactoryImplementor sessionFactory) { this.entityDescriptor = entityDescriptor; this.sessionFactory = sessionFactory; identifierMapping = getLoadable().getIdentifierMapping(); + idCoercionEnabled = + !sessionFactory.getSessionFactoryOptions() + .getJpaCompliance().isLoadByIdComplianceEnabled() + // special handling for entity with @IdClass + && !entityDescriptor.getIdentifierMapping().isVirtual(); } protected EntityMappingType getEntityDescriptor() { @@ -111,7 +118,6 @@ private List orderedMultiLoad( Object[] ids, MultiIdLoadOptions loadOptions, SharedSessionContractImplementor session) { - final boolean idCoercionEnabled = isIdCoercionEnabled(); final var idType = getLoadable().getIdentifierMapping().getJavaType(); final int maxBatchSize = maxBatchSize( ids, loadOptions ); @@ -124,7 +130,7 @@ private List orderedMultiLoad( final var lockOptions = lockOptions( loadOptions ); for ( int i = 0; i < ids.length; i++ ) { - final Object id = idCoercionEnabled ? idType.coerce( ids[i], session ) : ids[i]; + final Object id = coerce( session, idType, ids[i] ); final var entityKey = new EntityKey( id, getLoadable().getEntityPersister() ); if ( !loadFromEnabledCaches( loadOptions, session, id, lockOptions, entityKey, results, i ) ) { // if we did not hit any of the continues above, @@ -154,10 +160,13 @@ private List orderedMultiLoad( return (List) results; } + private Object coerce(SharedSessionContractImplementor session, JavaType idType, Object id) { + return idCoercionEnabled ? idType.coerce( id, session ) : id; + } + private static LockOptions lockOptions(MultiIdLoadOptions loadOptions) { - return loadOptions.getLockOptions() == null - ? new LockOptions( LockMode.NONE ) - : loadOptions.getLockOptions(); + final var lockOptions = loadOptions.getLockOptions(); + return lockOptions == null ? new LockOptions( LockMode.NONE ) : lockOptions; } protected abstract int maxBatchSize(Object[] ids, MultiIdLoadOptions loadOptions); @@ -169,8 +178,8 @@ private void handleResults( List results) { final var persistenceContext = session.getPersistenceContext(); for ( Integer position : elementPositionsLoadedByBatch ) { - // the element value at this position in the results List should be - // the EntityKey for that entity - reuse it + // the element value at this position in the results List + // should be the EntityKey for that entity - reuse it final var entityKey = (EntityKey) results.get( position ); session.getPersistenceContextInternal().getBatchFetchQueue().removeBatchLoadableEntityKey( entityKey ); final Object entity = persistenceContext.getEntity( entityKey ); @@ -330,11 +339,10 @@ private List unresolvedIds( LockOptions lockOptions, SharedSessionContractImplementor session, ResolutionConsumer resolutionConsumer) { - final boolean idCoercionEnabled = isIdCoercionEnabled(); final var idType = getLoadable().getIdentifierMapping().getJavaType(); List unresolvedIds = null; for ( int i = 0; i < ids.length; i++ ) { - final Object id = idCoercionEnabled ? idType.coerce( ids[i], session ) : ids[i]; + final Object id = coerce( session, idType, ids[i] ); unresolvedIds = loadFromCaches( loadOptions, @@ -353,10 +361,6 @@ private List unresolvedIds( // Depending on the implementation, a specific subtype of Object[] (e.g. Integer[]) may be needed. protected abstract Object[] toIdArray(List ids); - private boolean isIdCoercionEnabled() { - return !getSessionFactory().getSessionFactoryOptions().getJpaCompliance().isLoadByIdComplianceEnabled(); - } - public interface ResolutionConsumer { void consume(int position, EntityKey entityKey, T resolvedRef); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/IdentifierLoadAccessImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/IdentifierLoadAccessImpl.java index f8d38d956b43..d947ad688912 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/IdentifierLoadAccessImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/IdentifierLoadAccessImpl.java @@ -196,7 +196,10 @@ protected Object coerceId(Object id, SessionFactoryImplementor factory) { } else { try { - return entityPersister.getIdentifierMapping().getJavaType().coerce( id, this ); + final var identifierMapping = entityPersister.getIdentifierMapping(); + return identifierMapping.isVirtual() + ? id // special case for a class with an @IdClass + : identifierMapping.getJavaType().coerce( id, this ); } catch ( Exception e ) { throw new IllegalArgumentException( "Argument '" + id diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ValueMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ValueMapping.java index d2069e238121..e2f730dd19f3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ValueMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ValueMapping.java @@ -40,8 +40,7 @@ default JavaType getExpressibleJavaType() { */ default X treatAs(Class targetType) { if ( targetType.isInstance( this ) ) { - //noinspection unchecked - return (X) this; + return targetType.cast( this ); } throw new IllegalArgumentException( diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java index b81f892f4ff0..7dff3a5b2219 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java @@ -65,12 +65,12 @@ public NonAggregatedIdentifierMappingImpl( super( entityPersister, rootTableName, creationProcess ); entityDescriptor = entityPersister; - if ( bootEntityDescriptor.getIdentifierMapper() == null - || bootEntityDescriptor.getIdentifierMapper() == bootEntityDescriptor.getIdentifier() ) { + final var identifierMapper = bootEntityDescriptor.getIdentifierMapper(); + final var identifier = bootEntityDescriptor.getIdentifier(); + if ( identifierMapper == null || identifierMapper == identifier ) { // cid -> getIdentifier // idClass -> null - final Component virtualIdSource = (Component) bootEntityDescriptor.getIdentifier(); - + final var virtualIdSource = (Component) identifier; virtualIdEmbeddable = new VirtualIdEmbeddable( virtualIdSource, this, @@ -85,9 +85,8 @@ public NonAggregatedIdentifierMappingImpl( else { // cid = getIdentifierMapper // idClass = getIdentifier - final var virtualIdSource = bootEntityDescriptor.getIdentifierMapper(); - final var idClassSource = (Component) bootEntityDescriptor.getIdentifier(); - + final var virtualIdSource = identifierMapper; + final var idClassSource = (Component) identifier; virtualIdEmbeddable = new VirtualIdEmbeddable( virtualIdSource, this, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java index e412aa39bb02..410ae933c825 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java @@ -137,8 +137,8 @@ public EntityDomainType findEntityType(@Nullable String entityName) { return null; } - final ManagedDomainType managedType = managedTypeByName.get( entityName ); - if ( managedType instanceof EntityDomainType entityDomainType ){ + if ( managedTypeByName.get( entityName ) + instanceof EntityDomainType entityDomainType ){ return entityDomainType; } @@ -148,7 +148,7 @@ public EntityDomainType findEntityType(@Nullable String entityName) { // was no direct match, we need to iterate over all of the and look based on // JPA entity-name. - for ( Map.Entry> entry : managedTypeByName.entrySet() ) { + for ( var entry : managedTypeByName.entrySet() ) { if ( entry.getValue() instanceof EntityDomainType possibility ) { if ( entityName.equals( possibility.getName() ) ) { return possibility; @@ -176,7 +176,7 @@ public EmbeddableDomainType findEmbeddableType(@Nullable String embeddableNam if ( embeddableName == null ) { return null; } - final ManagedDomainType managedType = managedTypeByName.get( embeddableName ); + final var managedType = managedTypeByName.get( embeddableName ); if ( !( managedType instanceof EmbeddableDomainType embeddableDomainType ) ) { return null; } @@ -185,7 +185,7 @@ public EmbeddableDomainType findEmbeddableType(@Nullable String embeddableNam @Override public EmbeddableDomainType embeddable(String embeddableName) { - final EmbeddableDomainType embeddableType = findEmbeddableType( embeddableName ); + final var embeddableType = findEmbeddableType( embeddableName ); if ( embeddableType == null ) { throw new IllegalArgumentException( "Not an embeddable: " + embeddableName ); } @@ -195,21 +195,21 @@ public EmbeddableDomainType embeddable(String embeddableName) { @Override public EntityDomainType getHqlEntityReference(String entityName) { Class loadedClass = null; - final ImportInfo importInfo = resolveImport( entityName ); + final var importInfo = (ImportInfo) resolveImport( entityName ); if ( importInfo != null ) { loadedClass = importInfo.loadedClass; entityName = importInfo.importedName; } - final EntityDomainType entityDescriptor = findEntityType( entityName ); + final var entityDescriptor = findEntityType( entityName ); if ( entityDescriptor != null ) { //noinspection unchecked return (EntityDomainType) entityDescriptor; } if ( loadedClass == null ) { - loadedClass = resolveRequestedClass( entityName ); - // populate class cache for boot metamodel imports + loadedClass = (Class) resolveRequestedClass( entityName ); + // populate the class cache for boot metamodel imports if ( importInfo != null && loadedClass != null ) { importInfo.loadedClass = loadedClass; } @@ -238,7 +238,7 @@ public ManagedDomainType findManagedType(Class cls) { @Override public ManagedDomainType managedType(Class cls) { - final ManagedDomainType type = findManagedType( cls ); + final var type = findManagedType( cls ); if ( type == null ) { // per JPA throw new IllegalArgumentException( "Not a managed type: " + cls ); @@ -249,17 +249,16 @@ public ManagedDomainType managedType(Class cls) { @Override @Nullable public EntityDomainType findEntityType(Class cls) { - final ManagedType type = managedTypeByClass.get( cls ); - if ( !( type instanceof EntityDomainType ) ) { - return null; - } + final var type = managedTypeByClass.get( cls ); //noinspection unchecked - return (EntityDomainType) type; + return type instanceof EntityDomainType + ? (EntityDomainType) type + : null; } @Override public EntityDomainType entity(Class cls) { - final EntityDomainType entityType = findEntityType( cls ); + final var entityType = findEntityType( cls ); if ( entityType == null ) { throw new IllegalArgumentException( "Not an entity: " + cls.getName() ); } @@ -268,17 +267,16 @@ public EntityDomainType entity(Class cls) { @Override public @Nullable EmbeddableDomainType findEmbeddableType(Class cls) { - final ManagedType type = managedTypeByClass.get( cls ); - if ( !( type instanceof EmbeddableDomainType ) ) { - return null; - } + final var type = managedTypeByClass.get( cls ); //noinspection unchecked - return (EmbeddableDomainType) type; + return type instanceof EmbeddableDomainType + ? (EmbeddableDomainType) type + : null; } @Override public EmbeddableDomainType embeddable(Class cls) { - final EmbeddableDomainType embeddableType = findEmbeddableType( cls ); + final var embeddableType = findEmbeddableType( cls ); if ( embeddableType == null ) { throw new IllegalArgumentException( "Not an embeddable: " + cls.getName() ); } @@ -322,7 +320,7 @@ public Set> getEmbeddables() { @Override public EnumJavaType getEnumType(String className) { - final EnumJavaType enumJavaType = enumJavaTypes.get( className ); + final var enumJavaType = enumJavaTypes.get( className ); if ( enumJavaType != null ) { return enumJavaType; } @@ -383,7 +381,7 @@ private Field getJavaField(String className, String fieldName) throws NoSuchFiel @Override public void addNamedEntityGraph(String graphName, RootGraphImplementor rootGraph) { - final EntityGraph old = entityGraphMap.put( graphName, rootGraph.makeImmutableCopy( graphName ) ); + final var old = entityGraphMap.put( graphName, rootGraph.makeImmutableCopy( graphName ) ); if ( old != null ) { CORE_LOGGER.tracef( "EntityGraph named '%s' was replaced", graphName ); } @@ -396,7 +394,7 @@ public RootGraphImplementor findEntityGraphByName(String name) { @Override public List> findEntityGraphsByJavaType(Class entityClass) { - final EntityDomainType entityType = entity( entityClass ); + final var entityType = entity( entityClass ); if ( entityType == null ) { throw new IllegalArgumentException( "Given class is not an entity: " + entityClass.getName() ); } @@ -415,7 +413,7 @@ public List> findEntityGraphsByJavaType(Class enti @Override public Map> getNamedEntityGraphs(Class entityClass) { - final EntityDomainType entityType = entity( entityClass ); + final var entityType = entity( entityClass ); if ( entityType == null ) { throw new IllegalArgumentException( "Given class is not an entity: " + entityClass.getName() ); } @@ -438,12 +436,11 @@ public String qualifyImportableName(String queryName) { return importInfo == null ? null : importInfo.importedName; } - private ImportInfo resolveImport(final String name) { - final ImportInfo importInfo = nameToImportMap.get( name ); + private ImportInfo resolveImport(final String name) { + final var importInfo = nameToImportMap.get( name ); //optimal path first if ( importInfo != null ) { - //noinspection unchecked - return (ImportInfo) importInfo; + return importInfo; } else { //then check the negative cache, to avoid bothering the classloader unnecessarily @@ -451,10 +448,10 @@ private ImportInfo resolveImport(final String name) { return null; } else { - // see if the name is a fully-qualified class name - final Class loadedClass = resolveRequestedClass( name ); + // see if the name is a fully qualified class name + final Class loadedClass = resolveRequestedClass( name ); if ( loadedClass == null ) { - // it is NOT a fully-qualified class name - add a marker entry so we do not keep trying later + // it is NOT a fully qualified class name - add a marker entry, so we do not keep trying later // note that ConcurrentHashMap does not support null value so a marker entry is needed // [HHH-14948] But only add it if the cache size isn't getting too large, as in some use cases // the queries are dynamically generated and this cache could lead to memory leaks when left unbounded. @@ -470,9 +467,9 @@ private ImportInfo resolveImport(final String name) { return null; } else { - // it is a fully-qualified class name - add it to the cache + // it is a fully qualified class name - add it to the cache // so to not needing to load from the classloader again - final ImportInfo info = new ImportInfo<>( name, loadedClass ); + final ImportInfo info = new ImportInfo<>( name, loadedClass ); nameToImportMap.put( name, info ); return info; } @@ -481,24 +478,22 @@ private ImportInfo resolveImport(final String name) { } private void applyNamedEntityGraphs(Collection namedEntityGraphs) { - for ( NamedEntityGraphDefinition definition : namedEntityGraphs ) { + for ( var definition : namedEntityGraphs ) { CORE_LOGGER.tracef( "Applying named entity graph [name=%s, source=%s]", definition.name(), definition.source() ); final RootGraphImplementor graph = definition.graphCreator().createEntityGraph( (entityClass) -> { - final ManagedDomainType managedDomainType = managedTypeByClass.get( entityClass ); - if ( managedDomainType instanceof EntityDomainType match ) { + if ( managedTypeByClass.get( entityClass ) instanceof EntityDomainType match ) { return match; } throw new IllegalArgumentException( "Cannot resolve entity class : " + entityClass.getName() ); }, (jpaEntityName) -> { - for ( Map.Entry> entry : managedTypeByName.entrySet() ) { - if ( entry.getValue() instanceof EntityDomainType possibility ) { - if ( jpaEntityName.equals( possibility.getName() ) ) { - return possibility; - } + for ( var entry : managedTypeByName.entrySet() ) { + if ( entry.getValue() instanceof EntityDomainType possibility + && jpaEntityName.equals( possibility.getName() ) ) { + return possibility; } } throw new IllegalArgumentException( "Cannot resolve entity name : " + jpaEntityName ); @@ -509,7 +504,7 @@ private void applyNamedEntityGraphs(Collection named } - private Class resolveRequestedClass(String entityName) { + private Class resolveRequestedClass(String entityName) { try { return classLoaderService.classForName( entityName ); } @@ -522,7 +517,7 @@ private Class resolveRequestedClass(String entityName) { public EntityDomainType resolveEntityReference(Class javaType) { // try the incoming Java type as a "strict" entity reference { - final ManagedDomainType managedType = managedTypeByClass.get( javaType ); + final var managedType = managedTypeByClass.get( javaType ); if ( managedType instanceof EntityDomainType ) { return (EntityDomainType) managedType; } @@ -538,37 +533,34 @@ public EntityDomainType resolveEntityReference(Class javaType) { // otherwise, try to handle it as a polymorphic reference { - final EntityDomainType polymorphicDomainType = - (EntityDomainType) polymorphicEntityReferenceMap.get( javaType ); + final var polymorphicDomainType = + (EntityDomainType) + polymorphicEntityReferenceMap.get( javaType ); if ( polymorphicDomainType != null ) { return polymorphicDomainType; } // create a set of descriptors that should be used to build the polymorphic EntityDomainType final Set> matchingDescriptors = new HashSet<>(); - for ( ManagedDomainType managedType : managedTypeByName.values() ) { - if ( managedType.getPersistenceType() != Type.PersistenceType.ENTITY ) { - continue; - } - // see if we should add `entityDomainType` as one of the matching-descriptors. - if ( javaType.isAssignableFrom( managedType.getJavaType() ) ) { + for ( var managedType : managedTypeByName.values() ) { + if ( managedType.getPersistenceType() == Type.PersistenceType.ENTITY + // see if we should add EntityDomainType as one of the matching descriptors. + && javaType.isAssignableFrom( managedType.getJavaType() ) ) { // the queried type is assignable from the type of the current entity-type // we should add it to the collecting set of matching descriptors. it should // be added aside from a few cases... // if the managed-type has a super type and the java type is assignable from the super type, - // do not add the managed-type as the super itself will get added and the initializers for + // do not add the managed type as the super itself will get added and the initializers for // entity mappings already handle loading subtypes - adding it would be redundant and lead to // incorrect results - final ManagedDomainType superType = managedType.getSuperType(); - if ( superType != null - && superType.getPersistenceType() == Type.PersistenceType.ENTITY - && javaType.isAssignableFrom( superType.getJavaType() ) ) { - continue; + final var superType = managedType.getSuperType(); + if ( superType == null + || superType.getPersistenceType() != Type.PersistenceType.ENTITY + || !javaType.isAssignableFrom( superType.getJavaType() ) ) { + matchingDescriptors.add( (EntityDomainType) managedType ); } - // otherwise, add it - matchingDescriptors.add( (EntityDomainType) managedType ); } } @@ -604,10 +596,11 @@ public void processJpa( Collection namedEntityGraphDefinitions, RuntimeModelCreationContext runtimeModelCreationContext) { bootMetamodel.getImports() - .forEach( (key, value) -> this.nameToImportMap.put( key, new ImportInfo<>( value, null ) ) ); + .forEach( (key, value) -> nameToImportMap.put( key, + new ImportInfo<>( value, null ) ) ); this.entityProxyInterfaceMap.putAll( entityProxyInterfaceMap ); - final MetadataContext context = new MetadataContext( + final var context = new MetadataContext( this, mappingMetamodel, bootMetamodel, @@ -628,31 +621,31 @@ public void processJpa( this.jpaMetaModelPopulationSetting = jpaMetaModelPopulationSetting; // Identifiable types (Entities and MappedSuperclasses) - this.managedTypeByName.putAll( context.getIdentifiableTypesByName() ); - this.managedTypeByClass.putAll( context.getEntityTypeMap() ); - this.managedTypeByClass.putAll( context.getMappedSuperclassTypeMap() ); + managedTypeByName.putAll( context.getIdentifiableTypesByName() ); + managedTypeByClass.putAll( context.getEntityTypeMap() ); + managedTypeByClass.putAll( context.getMappedSuperclassTypeMap() ); // Embeddable types int mapEmbeddables = 0; - for ( EmbeddableDomainType embeddable : context.getEmbeddableTypeSet() ) { + for ( var embeddable : context.getEmbeddableTypeSet() ) { // Do not register the embeddable types for id classes if ( embeddable.getExpressibleJavaType() instanceof EntityJavaType ) { continue; } - final Class embeddableClass = embeddable.getJavaType(); + final var embeddableClass = embeddable.getJavaType(); if ( embeddableClass != Map.class ) { - this.managedTypeByClass.put( embeddable.getJavaType(), embeddable ); - this.managedTypeByName.put( embeddable.getTypeName(), embeddable ); + managedTypeByClass.put( embeddable.getJavaType(), embeddable ); + managedTypeByName.put( embeddable.getTypeName(), embeddable ); } else { - this.managedTypeByName.put( "dynamic-embeddable-" + mapEmbeddables++, embeddable ); + managedTypeByName.put( "dynamic-embeddable-" + mapEmbeddables++, embeddable ); } } typeConfiguration.getJavaTypeRegistry().forEachDescriptor( descriptor -> { if ( descriptor instanceof EnumJavaType> enumJavaType ) { - final Class> enumJavaClass = enumJavaType.getJavaTypeClass(); - for ( Enum enumConstant : enumJavaClass.getEnumConstants() ) { + final var enumJavaClass = enumJavaType.getJavaTypeClass(); + for ( var enumConstant : enumJavaClass.getEnumConstants() ) { addAllowedEnumLiteralsToEnumTypesMap( allowedEnumLiteralsToEnumTypeNames, enumConstant.name(), @@ -731,7 +724,8 @@ private EntityTypeImpl buildEntityType( MetadataContext context, TypeConfiguration typeConfiguration) { context.pushEntityWorkedOn( persistentClass ); - final var entityType = entityType( persistentClass, persistentClass.getMappedClass(), context, typeConfiguration ); + final var entityType = + entityType( persistentClass, persistentClass.getMappedClass(), context, typeConfiguration ); context.registerEntityType( persistentClass, entityType ); context.popEntityWorkedOn( persistentClass ); return entityType; @@ -760,9 +754,9 @@ private EntityTypeImpl entityType( } private void handleUnusedMappedSuperclasses(MetadataContext context, TypeConfiguration typeConfiguration) { - final Set unusedMappedSuperclasses = context.getUnusedMappedSuperclasses(); + final var unusedMappedSuperclasses = context.getUnusedMappedSuperclasses(); if ( !unusedMappedSuperclasses.isEmpty() ) { - for ( MappedSuperclass mappedSuperclass : unusedMappedSuperclasses ) { + for ( var mappedSuperclass : unusedMappedSuperclasses ) { CORE_LOGGER.unusedMappedSuperclass( mappedSuperclass.getMappedClass().getName() ); locateOrBuildMappedSuperclassType( mappedSuperclass, context, typeConfiguration ); } @@ -773,7 +767,7 @@ private MappedSuperclassDomainType locateOrBuildMappedSuperclassType( MappedSuperclass mappedSuperclass, MetadataContext context, TypeConfiguration typeConfiguration) { - final MappedSuperclassDomainType mappedSuperclassType = + final var mappedSuperclassType = context.locateMappedSuperclassType( mappedSuperclass ); return mappedSuperclassType == null ? buildMappedSuperclassType( mappedSuperclass, mappedSuperclass.getMappedClass(), context, typeConfiguration ) @@ -786,13 +780,13 @@ private MappedSuperclassTypeImpl buildMappedSuperclassType( MetadataContext context, TypeConfiguration typeConfiguration) { @SuppressWarnings("unchecked") - final IdentifiableDomainType superType = + final var superType = (IdentifiableDomainType) supertypeForMappedSuperclass( mappedSuperclass, context, typeConfiguration ); - final JavaType javaType = + final var javaType = context.getTypeConfiguration().getJavaTypeRegistry() .resolveManagedTypeDescriptor( mappedClass ); - final MappedSuperclassTypeImpl mappedSuperclassType = + final var mappedSuperclassType = new MappedSuperclassTypeImpl<>( javaType, mappedSuperclass, superType, this ); context.registerMappedSuperclassType( mappedSuperclass, mappedSuperclassType ); return mappedSuperclassType; @@ -802,15 +796,14 @@ private IdentifiableDomainType supertypeForPersistentClass( PersistentClass persistentClass, MetadataContext context, TypeConfiguration typeConfiguration) { - final MappedSuperclass superMappedSuperclass = persistentClass.getSuperMappedSuperclass(); - final IdentifiableDomainType supertype = + final var superMappedSuperclass = persistentClass.getSuperMappedSuperclass(); + final var supertype = superMappedSuperclass == null ? null : locateOrBuildMappedSuperclassType( superMappedSuperclass, context, typeConfiguration ); - - //no mappedSuperclass, check for a super entity if ( supertype == null ) { - final PersistentClass superPersistentClass = persistentClass.getSuperclass(); + // no mapped superclass, check for a super entity + final var superPersistentClass = persistentClass.getSuperclass(); return superPersistentClass == null ? null : locateOrBuildEntityType( superPersistentClass, context, typeConfiguration ); @@ -824,14 +817,14 @@ private IdentifiableDomainType supertypeForMappedSuperclass( MappedSuperclass mappedSuperclass, MetadataContext context, TypeConfiguration typeConfiguration) { - final MappedSuperclass superMappedSuperclass = mappedSuperclass.getSuperMappedSuperclass(); - final IdentifiableDomainType superType = + final var superMappedSuperclass = mappedSuperclass.getSuperMappedSuperclass(); + final var superType = superMappedSuperclass == null ? null : locateOrBuildMappedSuperclassType( superMappedSuperclass, context, typeConfiguration ); - //no mappedSuperclass, check for a super entity if ( superType == null ) { - final PersistentClass superPersistentClass = mappedSuperclass.getSuperPersistentClass(); + //no mapped superclass, check for a super entity + final var superPersistentClass = mappedSuperclass.getSuperPersistentClass(); return superPersistentClass == null ? null : locateOrBuildEntityType( superPersistentClass, context, typeConfiguration ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/specification/internal/ProjectionSpecificationImpl.java b/hibernate-core/src/main/java/org/hibernate/query/specification/internal/ProjectionSpecificationImpl.java index 61954c799819..07fb2d33babc 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/specification/internal/ProjectionSpecificationImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/specification/internal/ProjectionSpecificationImpl.java @@ -31,6 +31,8 @@ import java.util.Map; import java.util.function.BiFunction; +import static org.hibernate.internal.util.type.PrimitiveWrapperHelper.cast; + /** * @author Gavin King */ @@ -47,14 +49,14 @@ public ProjectionSpecificationImpl(SelectionSpecification selectionSpecificat public Element select(SingularAttribute attribute) { final int position = specifications.size(); specifications.add( (select, root) -> root.get( attribute ) ); - return tuple -> (X) tuple[position]; + return tuple -> cast( attribute.getJavaType(), tuple[position] ); } @Override public Element select(Path path) { final int position = specifications.size(); specifications.add( (select, root) -> (SqmPath) path.path( root ) ); - return tuple -> (X) tuple[position]; + return tuple -> cast( path.getType(), tuple[position] ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java index a82b490e1e55..b6678db8e43c 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java @@ -758,6 +758,7 @@ public T getParameterValue(Parameter param) { } if ( binding.isMultiValued() ) { + // TODO: THIS IS UNSOUND //noinspection unchecked return (T) binding.getBindValues(); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java index c9678488ca50..f96a66ad04ae 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java @@ -43,7 +43,6 @@ import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityVersionMapping; -import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.PersistentAttribute; import org.hibernate.metamodel.model.domain.internal.EntitySqmPathSource; @@ -143,7 +142,6 @@ import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.java.EnumJavaType; import org.hibernate.type.descriptor.java.JavaType; -import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.spi.TypeConfiguration; import jakarta.persistence.Tuple; @@ -1558,7 +1556,7 @@ private SqmLiteral createLiteral(T value, SqmBindableType expressible) final T coercedValue = expressible.getExpressibleJavaType() .coerce( value, this::getTypeConfiguration ); - // ignore typeInferenceSource and fallback the value type + // ignore typeInferenceSource and fall back to the value type return expressible.getExpressibleJavaType().isInstance( coercedValue ) ? new SqmLiteral<>( coercedValue, expressible, this ) : literal( value ); @@ -1579,9 +1577,9 @@ else if ( value == null ) { } private BasicType resolveInferredType(T value) { - final TypeConfiguration typeConfiguration = getTypeConfiguration(); - final Class type = ReflectHelper.getClass( value ); - final BasicType result = typeConfiguration.getBasicTypeForJavaType( type ); + final var typeConfiguration = getTypeConfiguration(); + final var type = ReflectHelper.getClass( value ); + final var result = typeConfiguration.getBasicTypeForJavaType( type ); if ( result == null && value instanceof Enum enumValue ) { return (BasicType) resolveEnumType( typeConfiguration, enumValue ); } @@ -1591,9 +1589,9 @@ private BasicType resolveInferredType(T value) { } private static > BasicType resolveEnumType(TypeConfiguration configuration, Enum enumValue) { - final EnumJavaType javaType = new EnumJavaType<>( ReflectHelper.getClass( enumValue ) ); - final JdbcType jdbcType = javaType.getRecommendedJdbcType( configuration.getCurrentBaseSqlTypeIndicators() ); - return configuration.getBasicTypeRegistry().resolve( javaType, jdbcType ); + final var enumJavaType = new EnumJavaType<>( ReflectHelper.getClass( enumValue ) ); + final var jdbcType = enumJavaType.getRecommendedJdbcType( configuration.getCurrentBaseSqlTypeIndicators() ); + return configuration.getBasicTypeRegistry().resolve( enumJavaType, jdbcType ); } @Override @@ -1647,9 +1645,10 @@ public SqmExpression nullLiteral(Class resultClass) { return new SqmLiteralNull<>( this ); } else { - final BasicType basicTypeForJavaType = getTypeConfiguration().getBasicTypeForJavaType( resultClass ); + final var basicTypeForJavaType = + getTypeConfiguration().getBasicTypeForJavaType( resultClass ); // if there's no basic type, it might be an entity type - final SqmBindableType sqmExpressible = + final var sqmExpressible = basicTypeForJavaType == null ? resolveExpressible( getDomainModel().managedType( resultClass ) ) : basicTypeForJavaType; @@ -1692,8 +1691,8 @@ public JpaCriteriaParameter parameter(Class paramClass) { @Override public JpaCriteriaParameter parameter(Class paramClass, @Nullable String name) { - final BasicType basicType = getTypeConfiguration().getBasicTypeForJavaType( paramClass ); - boolean notBasic = basicType == null; + final var basicType = getTypeConfiguration().getBasicTypeForJavaType( paramClass ); + final boolean notBasic = basicType == null; final BindableType parameterType = notBasic && Collection.class.isAssignableFrom( paramClass ) // a Collection-valued, multi-valued parameter @@ -1709,7 +1708,7 @@ public JpaParameterExpression> listParameter(Class paramClass) { @Override public JpaParameterExpression> listParameter(Class paramClass, @Nullable String name) { - final BindableType> parameterType = new MultiValueParameterType<>( (Class>) (Class) List.class ); + final var parameterType = new MultiValueParameterType<>( (Class>) (Class) List.class ); return new JpaCriteriaParameter<>( name, parameterType, true, this ); } @@ -2198,7 +2197,7 @@ private ValueBindJpaCriteriaParameter valueParameter(@Nullable T value, @ final T coercedValue = resolveExpressible( bindableType ).getExpressibleJavaType() .coerce( value, this::getTypeConfiguration ); - // ignore typeInferenceSource and fall back the value type + // ignore typeInferenceSource and fall back to the value type if ( isInstance( bindableType, coercedValue ) ) { @SuppressWarnings("unchecked") // safe, we just checked final var widerType = (BindableType) bindableType; @@ -2208,23 +2207,28 @@ private ValueBindJpaCriteriaParameter valueParameter(@Nullable T value, @ } private ValueBindJpaCriteriaParameter> collectionValueParameter(Collection value, SqmExpression elementTypeInferenceSource) { - BindableType bindableType = null; + final var elementType = + resolveExpressible( bindableType( elementTypeInferenceSource ) ) + .getSqmType(); + if ( elementType == null ) { + throw new UnsupportedOperationException( "Can't infer collection type based on element expression: " + elementTypeInferenceSource ); + } + final var collectionType = DdlTypeHelper.resolveListType( elementType, getTypeConfiguration() ); + //noinspection unchecked + return new ValueBindJpaCriteriaParameter<>( (BasicType>) collectionType, value, this ); + } + + private static BindableType bindableType(SqmExpression elementTypeInferenceSource) { if ( elementTypeInferenceSource != null ) { if ( elementTypeInferenceSource instanceof BindableType ) { //noinspection unchecked - bindableType = (BindableType) elementTypeInferenceSource; + return (BindableType) elementTypeInferenceSource; } else if ( elementTypeInferenceSource.getNodeType() != null ) { - bindableType = elementTypeInferenceSource.getNodeType(); + return elementTypeInferenceSource.getNodeType(); } } - final DomainType elementType = resolveExpressible( bindableType ).getSqmType(); - if ( elementType == null ) { - throw new UnsupportedOperationException( "Can't infer collection type based on element expression: " + elementTypeInferenceSource ); - } - final BasicType collectionType = DdlTypeHelper.resolveListType( elementType, getTypeConfiguration() ); - //noinspection unchecked - return new ValueBindJpaCriteriaParameter<>( (BasicType>) collectionType, value, this ); + return null; } private ValueBindJpaCriteriaParameter valueParameter(T value) { @@ -2287,16 +2291,11 @@ public SqmExpression nullif(Expression x, Y y) { } private SqmExpression createNullifFunctionNode(SqmExpression first, SqmExpression second) { - final SqmBindableType bindableType = - highestPrecedenceType( first.getExpressible(), second.getExpressible() ); + final var bindableType = highestPrecedenceType( first.getExpressible(), second.getExpressible() ); @SuppressWarnings("unchecked") - final ReturnableType resultType = - bindableType == null ? null : (ReturnableType) bindableType.getSqmType(); - return getFunctionDescriptor( "nullif" ).generateSqmExpression( - asList( first, second ), - resultType, - getQueryEngine() - ); + final var resultType = bindableType == null ? null : (ReturnableType) bindableType.getSqmType(); + return getFunctionDescriptor( "nullif" ) + .generateSqmExpression( asList( first, second ), resultType, getQueryEngine() ); } private SqmFunctionDescriptor getFunctionDescriptor(String name) { @@ -2352,7 +2351,7 @@ public SqmPredicate and(Predicate... restrictions) { } final List predicates = new ArrayList<>( restrictions.length ); - for ( Predicate expression : restrictions ) { + for ( var expression : restrictions ) { predicates.add( (SqmPredicate) expression ); } return new SqmJunctionPredicate( Predicate.BooleanOperator.AND, predicates, this ); @@ -2365,7 +2364,7 @@ public SqmPredicate and(List restrictions) { } final List predicates = new ArrayList<>( restrictions.size() ); - for ( Predicate expression : restrictions ) { + for ( var expression : restrictions ) { predicates.add( (SqmPredicate) expression ); } return new SqmJunctionPredicate( Predicate.BooleanOperator.AND, predicates, this ); @@ -2388,7 +2387,7 @@ public SqmPredicate or(Predicate... restrictions) { } final List predicates = new ArrayList<>( restrictions.length ); - for ( Predicate expression : restrictions ) { + for ( var expression : restrictions ) { predicates.add( (SqmPredicate) expression ); } return new SqmJunctionPredicate( Predicate.BooleanOperator.OR, predicates, this ); @@ -2401,7 +2400,7 @@ public SqmPredicate or(List restrictions) { } final List predicates = new ArrayList<>( restrictions.size() ); - for ( Predicate expression : restrictions ) { + for ( var expression : restrictions ) { predicates.add( (SqmPredicate) expression ); } return new SqmJunctionPredicate( Predicate.BooleanOperator.OR, predicates, this ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java index 07e04313402b..78483d6625b4 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java @@ -5812,10 +5812,8 @@ else if ( Character.class.isAssignableFrom( valueConverter.getRelationalJavaType // so we allow coercion between the number types else if ( Number.class.isAssignableFrom( valueConverter.getRelationalJavaType().getJavaTypeClass() ) && value instanceof Number ) { - return valueConverter.getRelationalJavaType().coerce( - value, - creationContext::getTypeConfiguration - ); + return valueConverter.getRelationalJavaType() + .coerce( value, creationContext::getTypeConfiguration ); } else { throw new SemanticException( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java index dac9754aa13d..937e489afd3a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java @@ -33,7 +33,6 @@ import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.SqmPathSource; -import org.hibernate.query.sqm.spi.SqmCreationHelper; import org.hibernate.query.sqm.tree.SqmCopyContext; import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.SqmRenderContext; @@ -66,6 +65,7 @@ import static java.util.Collections.emptyList; import static java.util.Collections.unmodifiableList; import static org.hibernate.query.sqm.internal.SqmUtil.findCompatibleFetchJoin; +import static org.hibernate.query.sqm.spi.SqmCreationHelper.buildRootNavigablePath; /** * Convenience base class for SqmFrom implementations @@ -100,7 +100,7 @@ protected AbstractSqmFrom( @Nullable String alias, NodeBuilder nodeBuilder) { super( - SqmCreationHelper.buildRootNavigablePath( entityType.getHibernateEntityName(), alias ), + buildRootNavigablePath( entityType.getHibernateEntityName(), alias ), (SqmEntityDomainType) entityType, null, nodeBuilder @@ -118,7 +118,6 @@ protected AbstractSqmFrom( @Nullable String alias, NodeBuilder nodeBuilder) { super( navigablePath, entityType, null, nodeBuilder ); - this.alias = alias; } @@ -136,16 +135,18 @@ protected void copyTo(AbstractSqmFrom target, SqmCopyContext context) { super.copyTo( target, context ); final var joins = this.joins; if ( joins != null ) { - final ArrayList> newJoins = new ArrayList<>( joins.size() ); - for ( SqmJoin join : joins ) { + final ArrayList> newJoins = + new ArrayList<>( joins.size() ); + for ( var join : joins ) { newJoins.add( join.copy( context ) ); } target.joins = newJoins; } final var treats = this.treats; if ( treats != null ) { - final ArrayList> newTreats = new ArrayList<>( treats.size() ); - for ( SqmTreatedFrom treat : treats ) { + final ArrayList> newTreats = + new ArrayList<>( treats.size() ); + for ( var treat : treats ) { newTreats.add( treat.copy( context ) ); } target.treats = newTreats; @@ -169,7 +170,7 @@ public SqmPath resolvePathPart( SqmCreationState creationState) { // Try to resolve an existing attribute join without ON clause SqmPath resolvedPath = null; - for ( SqmJoin sqmJoin : getSqmJoins() ) { + for ( var sqmJoin : getSqmJoins() ) { // We can only match singular joins here, as plural path parts are interpreted like sub-queries if ( sqmJoin instanceof SqmSingularJoin attributeJoin && name.equals( sqmJoin.getReferencedPathSource().getPathName() ) ) { @@ -268,7 +269,7 @@ public void visitSqmJoins(Consumer> consumer) { protected > @Nullable X findTreat(ManagedDomainType targetType, @Nullable String alias) { if ( treats != null ) { - for ( SqmTreatedFrom treat : treats ) { + for ( var treat : treats ) { if ( treat.getModel() == targetType ) { if ( Objects.equals( treat.getExplicitAlias(), alias ) ) { //noinspection unchecked @@ -332,7 +333,7 @@ public SqmSingularJoin join(SingularAttribute attribute) @Override public SqmSingularJoin join(SingularAttribute attribute, JoinType jt) { - final SqmSingularJoin join = + final var join = buildSingularJoin( (SqmSingularPersistentAttribute) attribute, SqmJoinType.from( jt ), false ); addSqmJoin( join ); @@ -352,8 +353,8 @@ public SqmEntityJoin join(EntityDomainType targetEntityDescriptor) @Override public SqmEntityJoin join(EntityDomainType targetEntityDescriptor, SqmJoinType joinType) { //noinspection unchecked - final SqmRoot root = (SqmRoot) findRoot(); - final SqmEntityJoin sqmEntityJoin = new SqmEntityJoin<>( + final var root = (SqmRoot) findRoot(); + final var sqmEntityJoin = new SqmEntityJoin<>( targetEntityDescriptor, generateAlias(), joinType, @@ -370,7 +371,7 @@ public SqmBagJoin join(CollectionAttribute attribute) { @Override public SqmBagJoin join(CollectionAttribute attribute, JoinType jt) { - final SqmBagJoin join = buildBagJoin( + final var join = buildBagJoin( (BagPersistentAttribute) attribute, SqmJoinType.from( jt ), false @@ -386,7 +387,7 @@ public SqmSetJoin join(SetAttribute attribute) { @Override public SqmSetJoin join(SetAttribute attribute, JoinType jt) { - final SqmSetJoin join = buildSetJoin( + final var join = buildSetJoin( (SetPersistentAttribute) attribute, SqmJoinType.from( jt ), false @@ -402,7 +403,7 @@ public SqmListJoin join(ListAttribute attribute) { @Override public SqmListJoin join(ListAttribute attribute, JoinType jt) { - final SqmListJoin join = buildListJoin( + final var join = buildListJoin( (ListPersistentAttribute) attribute, SqmJoinType.from( jt ), false @@ -418,7 +419,7 @@ public SqmMapJoin join(MapAttribute attribute) @Override public SqmMapJoin join(MapAttribute attribute, JoinType jt) { - final SqmMapJoin join = buildMapJoin( + final var join = buildMapJoin( (MapPersistentAttribute) attribute, SqmJoinType.from( jt ), false @@ -435,7 +436,7 @@ public SqmAttributeJoin join(String attributeName) { @Override @SuppressWarnings("unchecked") public SqmAttributeJoin join(String attributeName, JoinType jt) { - final SqmPathSource subPathSource = (SqmPathSource) + final var subPathSource = (SqmPathSource) getReferencedPathSource().getSubPathSource( attributeName ); return (SqmAttributeJoin) buildJoin( subPathSource, SqmJoinType.from( jt ), false ); } @@ -448,10 +449,9 @@ public SqmBagJoin joinCollection(String attributeName) { @Override @SuppressWarnings("unchecked") public SqmBagJoin joinCollection(String attributeName, JoinType jt) { - final SqmPathSource joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName ); - + final var joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName ); if ( joinedPathSource instanceof BagPersistentAttribute ) { - final SqmBagJoin join = buildBagJoin( + final var join = buildBagJoin( (BagPersistentAttribute) joinedPathSource, SqmJoinType.from( jt ), false @@ -479,10 +479,9 @@ public SqmSetJoin joinSet(String attributeName) { @Override @SuppressWarnings("unchecked") public SqmSetJoin joinSet(String attributeName, JoinType jt) { - final SqmPathSource joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName ); - + final var joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName ); if ( joinedPathSource instanceof SetPersistentAttribute ) { - final SqmSetJoin join = buildSetJoin( + final var join = buildSetJoin( (SetPersistentAttribute) joinedPathSource, SqmJoinType.from( jt ), false @@ -510,10 +509,10 @@ public SqmListJoin joinList(String attributeName) { @Override @SuppressWarnings("unchecked") public SqmListJoin joinList(String attributeName, JoinType jt) { - final SqmPathSource joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName ); + final var joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName ); if ( joinedPathSource instanceof ListPersistentAttribute ) { - final SqmListJoin join = buildListJoin( + final var join = buildListJoin( (ListPersistentAttribute) joinedPathSource, SqmJoinType.from( jt ), false @@ -541,10 +540,10 @@ public SqmMapJoin joinMap(String attributeName) { @Override @SuppressWarnings("unchecked") public SqmMapJoin joinMap(String attributeName, JoinType jt) { - final SqmPathSource joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName ); + final var joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName ); if ( joinedPathSource instanceof MapPersistentAttribute ) { - final SqmMapJoin join = buildMapJoin( + final var join = buildMapJoin( (MapPersistentAttribute) joinedPathSource, SqmJoinType.from( jt ), false @@ -582,8 +581,8 @@ public SqmEntityJoin join(Class entityJavaType, JoinType joinType) @Override public SqmEntityJoin join(EntityType entity, JoinType joinType) { //noinspection unchecked - final SqmEntityJoin join = - new SqmEntityJoin<>( entity, generateAlias(), joinType, (SqmRoot) findRoot() ); + final var root = (SqmRoot) findRoot(); + final var join = new SqmEntityJoin<>( entity, generateAlias(), joinType, root ); addSqmJoin( join ); return join; } @@ -616,11 +615,11 @@ public JpaDerivedJoin join(Subquery subquery, SqmJoinType joinType, bo public JpaDerivedJoin join(Subquery subquery, SqmJoinType joinType, boolean lateral, String alias) { validateComplianceFromSubQuery(); //noinspection unchecked - final JpaDerivedJoin join = + final var derivedJoin = new SqmDerivedJoin<>( (SqmSubQuery) subquery, alias, joinType, lateral, (SqmRoot) findRoot() ); //noinspection unchecked - addSqmJoin( (SqmJoin) join ); - return join; + addSqmJoin( (SqmJoin) derivedJoin ); + return derivedJoin; } @Override @@ -636,11 +635,11 @@ public SqmJoin join(JpaCteCriteria cte, SqmJoinType joinType) { public SqmJoin join(JpaCteCriteria cte, SqmJoinType joinType, String alias) { validateComplianceFromSubQuery(); //noinspection unchecked - final SqmJoin join = + final var cteJoin = new SqmCteJoin<>( ( SqmCteStatement ) cte, alias, joinType, (SqmRoot) findRoot() ); //noinspection unchecked - addSqmJoin( (SqmJoin) join ); - return join; + addSqmJoin( (SqmJoin) cteJoin ); + return cteJoin; } @Override @@ -667,7 +666,7 @@ public JpaFunctionJoin join(JpaSetReturningFunction function) { public JpaFunctionJoin join(JpaSetReturningFunction function, SqmJoinType joinType, boolean lateral) { validateComplianceFromFunction(); //noinspection unchecked - final SqmFunctionJoin join = + final var functionJoin = new SqmFunctionJoin<>( (SqmSetReturningFunction) function, generateAlias(), @@ -675,8 +674,8 @@ public JpaFunctionJoin join(JpaSetReturningFunction function, SqmJoinT (SqmRoot) findRoot() ); //noinspection unchecked - addSqmJoin( (SqmJoin) join ); - return join; + addSqmJoin( (SqmJoin) functionJoin ); + return functionJoin; } @Override @@ -744,7 +743,7 @@ public JpaCrossJoin crossJoin(Class entityJavaType) { @Override public JpaCrossJoin crossJoin(EntityDomainType entity) { - final SqmCrossJoin crossJoin = + final var crossJoin = new SqmCrossJoin<>( (SqmEntityDomainType) entity, generateAlias(), findRoot() ); // noinspection unchecked addSqmJoin( (SqmJoin) crossJoin ); @@ -768,14 +767,13 @@ public SqmSingularJoin fetch(SingularAttribute attribute) @Override public SqmSingularJoin fetch(SingularAttribute attribute, JoinType jt) { final var persistentAttribute = (SqmSingularPersistentAttribute) attribute; - final SqmAttributeJoin compatibleFetchJoin = + final var compatibleFetchJoin = findCompatibleFetchJoin( this, persistentAttribute, SqmJoinType.from( jt ) ); if ( compatibleFetchJoin != null ) { return (SqmSingularJoin) compatibleFetchJoin; } - final SqmSingularJoin join = - buildSingularJoin( persistentAttribute, SqmJoinType.from( jt ), true ); + final var join = buildSingularJoin( persistentAttribute, SqmJoinType.from( jt ), true ); addSqmJoin( join ); return join; } @@ -816,15 +814,14 @@ private SqmAttributeJoin buildJoin( SqmJoinType joinType, boolean fetched) { if ( fetched ) { - final SqmAttributeJoin compatibleFetchJoin = + final var compatibleFetchJoin = findCompatibleFetchJoin( this, joinedPathSource, joinType ); if ( compatibleFetchJoin != null ) { return compatibleFetchJoin; } } - final SqmAttributeJoin sqmJoin = - buildAttributeJoin( joinedPathSource, joinType, fetched ); + final var sqmJoin = buildAttributeJoin( joinedPathSource, joinType, fetched ); addSqmJoin( sqmJoin ); return sqmJoin; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmJsonNullBehavior.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmJsonNullBehavior.java index 7cab17b40b01..8bc7759db8a3 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmJsonNullBehavior.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmJsonNullBehavior.java @@ -52,12 +52,7 @@ public X accept(SemanticQueryWalker walker) { @Override public void appendHqlString(StringBuilder hql, SqmRenderContext context) { - if ( this == NULL ) { - hql.append( " null on null" ); - } - else { - hql.append( " absent on null" ); - } + hql.append( this == NULL ? " null on null" : " absent on null" ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/AbstractSqmSelectQuery.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/AbstractSqmSelectQuery.java index 996ba715ca3e..eb8006d81821 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/AbstractSqmSelectQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/AbstractSqmSelectQuery.java @@ -90,7 +90,7 @@ public AbstractSqmSelectQuery( protected Map> copyCteStatements(SqmCopyContext context) { final Map> copies = new LinkedHashMap<>( cteStatements.size() ); - for ( Map.Entry> entry : cteStatements.entrySet() ) { + for ( var entry : cteStatements.entrySet() ) { copies.put( entry.getKey(), entry.getValue().copy( context ) ); } return copies; @@ -181,7 +181,7 @@ private String validateCteName(String name) { } protected JpaCteCriteria withInternal(String name, AbstractQuery criteria) { - final SqmCteStatement cteStatement = new SqmCteStatement<>( + final var cteStatement = new SqmCteStatement<>( name, (SqmSelectQuery) criteria, this, @@ -198,7 +198,7 @@ protected JpaCteCriteria withInternal( AbstractQuery baseCriteria, boolean unionDistinct, Function, AbstractQuery> recursiveCriteriaProducer) { - final SqmCteStatement cteStatement = new SqmCteStatement<>( + final var cteStatement = new SqmCteStatement<>( name, (SqmSelectQuery) baseCriteria, unionDistinct, @@ -247,7 +247,7 @@ public List> getRootList() { * @see org.hibernate.query.criteria.JpaCriteriaQuery#getRoot(int, Class) */ public JpaRoot getRoot(int position, Class type) { - final List> rootList = getQuerySpec().getRootList(); + final var rootList = getQuerySpec().getRootList(); if ( rootList.size() <= position ) { throw new IllegalArgumentException( "Not enough root entities" ); } @@ -258,7 +258,7 @@ public JpaRoot getRoot(int position, Class type) { * @see org.hibernate.query.criteria.JpaCriteriaQuery#getRoot(String, Class) */ public JpaRoot getRoot(String alias, Class type) { - for ( SqmRoot root : getQuerySpec().getRootList() ) { + for ( var root : getQuerySpec().getRootList() ) { final String rootAlias = root.getAlias(); if ( rootAlias != null && rootAlias.equals( alias ) ) { return castRoot( root, type ); @@ -268,7 +268,7 @@ public JpaRoot getRoot(String alias, Class type) { } private static JpaRoot castRoot(JpaRoot root, Class type) { - final Class rootEntityType = root.getJavaType(); + final var rootEntityType = root.getJavaType(); if ( rootEntityType == null ) { throw new AssertionFailure( "Java type of root entity was null" ); } @@ -277,7 +277,7 @@ private static JpaRoot castRoot(JpaRoot root, Class type) + "' did not have the given type '" + type.getTypeName() + "'"); } @SuppressWarnings("unchecked") // safe, we just checked - final JpaRoot result = (JpaRoot) root; + final var result = (JpaRoot) root; return result; } @@ -296,20 +296,20 @@ public SqmRoot from(Class entityClass) { @Override public SqmDerivedRoot from(Subquery subquery) { validateComplianceFromSubQuery(); - final SqmDerivedRoot root = new SqmDerivedRoot<>( (SqmSubQuery) subquery, null ); + final var root = new SqmDerivedRoot<>( (SqmSubQuery) subquery, null ); addRoot( root ); return root; } public JpaRoot from(JpaCteCriteria cte) { - final SqmCteRoot root = new SqmCteRoot<>( ( SqmCteStatement ) cte, null ); + final var root = new SqmCteRoot<>( ( SqmCteStatement ) cte, null ); addRoot( root ); return root; } @Override public JpaFunctionRoot from(JpaSetReturningFunction function) { - final SqmFunctionRoot root = new SqmFunctionRoot<>( (SqmSetReturningFunction) function, null ); + final var root = new SqmFunctionRoot<>( (SqmSetReturningFunction) function, null ); addRoot( root ); return root; } @@ -355,8 +355,8 @@ public SqmSelectQuery distinct(boolean distinct) { @Override public @Nullable JpaSelection getSelection() { - final SqmSelectClause selectClause = getQuerySpec().getSelectClause(); - final List> selections = selectClause.getSelections(); + final var selectClause = getQuerySpec().getSelectClause(); + final var selections = selectClause.getSelections(); return (JpaSelection) switch ( selections.size() ) { case 0 -> null; case 1 -> selections.get( 0 ).getSelectableNode(); @@ -438,7 +438,7 @@ public AbstractQuery having(List restrictions) { public void appendHqlString(StringBuilder hql, SqmRenderContext context) { if ( !cteStatements.isEmpty() ) { hql.append( "with " ); - for ( SqmCteStatement value : cteStatements.values() ) { + for ( var value : cteStatements.values() ) { value.appendHqlString( hql, context ); hql.append( ", " ); } @@ -479,7 +479,7 @@ public int cacheHashCode() { @SuppressWarnings("unchecked") protected Selection getResultSelection(Selection[] selections) { - final Class resultType = getResultType(); + final var resultType = getResultType(); if ( resultType == Object.class ) { return switch ( selections.length ) { case 0 -> throw new IllegalArgumentException( "Empty selections passed to criteria query typed as Object" ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcOperationQuery.java b/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcOperationQuery.java index e111c2a17e7c..1c192f43dc3b 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcOperationQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcOperationQuery.java @@ -90,9 +90,8 @@ public boolean isCompatibleWith(JdbcParameterBindings jdbcParameterBindings, Que return true; } - @SuppressWarnings("unchecked") static boolean equal(JdbcParameterBinding appliedBinding, JdbcParameterBinding binding, JavaType type) { return type.isInstance( appliedBinding.getBindValue() ) - && type.areEqual( (T) binding.getBindValue(), (T) appliedBinding.getBindValue() ); + && type.areEqual( type.cast( binding.getBindValue() ), type.cast( appliedBinding.getBindValue() ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java index 5b9901f60ca2..0cbefbe2b05d 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java @@ -13,7 +13,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerData; -import org.hibernate.sql.results.graph.entity.EntityInitializer; import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingResolution; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.spi.RowReader; @@ -25,7 +24,6 @@ /** * @author Steve Ebersole */ -@SuppressWarnings("rawtypes") public class StandardRowReader implements RowReader { private final DomainResultAssembler[] resultAssemblers; private final Initializer[] resultInitializers; @@ -36,7 +34,7 @@ public class StandardRowReader implements RowReader { private final InitializerData[] sortedForResolveInstanceData; private final boolean hasCollectionInitializers; private final @Nullable RowTransformer rowTransformer; - private final Class domainResultJavaType; + private final @Nullable Class domainResultJavaType; private final ComponentType componentType; private final Class resultElementClass; @@ -44,7 +42,7 @@ public class StandardRowReader implements RowReader { public StandardRowReader( JdbcValuesMappingResolution jdbcValuesMappingResolution, RowTransformer rowTransformer, - Class domainResultJavaType) { + @Nullable Class domainResultJavaType) { this( jdbcValuesMappingResolution.getDomainResultAssemblers(), jdbcValuesMappingResolution.getResultInitializers(), @@ -63,7 +61,7 @@ public StandardRowReader( Initializer[] sortedForResolveInitializers, boolean hasCollectionInitializers, RowTransformer rowTransformer, - Class domainResultJavaType) { + @Nullable Class domainResultJavaType) { this.resultAssemblers = resultAssemblers; this.resultInitializers = (Initializer[]) resultInitializers; this.resultInitializersData = new InitializerData[resultInitializers.length]; @@ -72,11 +70,12 @@ public StandardRowReader( this.sortedForResolveInstance = (Initializer[]) sortedForResolveInitializers; this.sortedForResolveInstanceData = new InitializerData[sortedForResolveInstance.length]; this.hasCollectionInitializers = hasCollectionInitializers; - this.rowTransformer = rowTransformer == RowTransformerArrayImpl.instance() && resultAssemblers.length != 1 + this.rowTransformer = + rowTransformer == RowTransformerArrayImpl.instance() && resultAssemblers.length != 1 || rowTransformer == RowTransformerStandardImpl.instance() || rowTransformer == RowTransformerSingularReturnImpl.instance() && resultAssemblers.length == 1 - ? null - : rowTransformer; + ? null + : rowTransformer; this.domainResultJavaType = domainResultJavaType; if ( domainResultJavaType == null || domainResultJavaType == Object[].class @@ -100,8 +99,8 @@ public Class getDomainResultResultJavaType() { @Override public List<@Nullable JavaType> getResultJavaTypes() { - List> javaTypes = new ArrayList<>( resultAssemblers.length ); - for ( DomainResultAssembler resultAssembler : resultAssemblers ) { + final List> javaTypes = new ArrayList<>( resultAssemblers.length ); + for ( var resultAssembler : resultAssemblers ) { javaTypes.add( resultAssembler.getAssembledJavaType() ); } return javaTypes; @@ -114,15 +113,18 @@ public int getInitializerCount() { @Override public @Nullable EntityKey resolveSingleResultEntityKey(RowProcessingState rowProcessingState) { - final EntityInitializer entityInitializer = resultInitializers.length == 0 - ? null - : resultInitializers[0].asEntityInitializer(); + final var entityInitializer = + resultInitializers.length == 0 + ? null + : resultInitializers[0].asEntityInitializer(); if ( entityInitializer == null ) { return null; } - final EntityKey entityKey = entityInitializer.resolveEntityKeyOnly( rowProcessingState ); - finishUpRow(); - return entityKey; + else { + final var entityKey = entityInitializer.resolveEntityKeyOnly( rowProcessingState ); + finishUpRow(); + return entityKey; + } } @Override @@ -133,34 +135,32 @@ public boolean hasCollectionInitializers() { @Override @AllowReflection public T readRow(RowProcessingState rowProcessingState) { - coordinateInitializers( rowProcessingState ); + coordinateInitializers(); + final T result = getResult( rowProcessingState ); + finishUpRow(); + return result; + } - final T result; + @SuppressWarnings("unchecked") + private T getResult(RowProcessingState rowProcessingState) { if ( componentType != ComponentType.OBJECT ) { - result = readPrimitiveRow( rowProcessingState ); + return (T) readPrimitiveRow( rowProcessingState ); + } + else if ( resultAssemblers.length == 1 && rowTransformer == null ) { + return (T) resultAssemblers[0].assemble( rowProcessingState ); } else { - if ( resultAssemblers.length == 1 && rowTransformer == null ) { - //noinspection unchecked - result = (T) resultAssemblers[0].assemble( rowProcessingState ); - } - else { - final Object[] resultRow = (Object[]) Array.newInstance( resultElementClass, resultAssemblers.length ); - for ( int i = 0; i < resultAssemblers.length; i++ ) { - resultRow[i] = resultAssemblers[i].assemble( rowProcessingState ); - } - //noinspection unchecked - result = rowTransformer == null - ? (T) resultRow - : rowTransformer.transformRow( resultRow ); + final var resultRow = (Object[]) Array.newInstance( resultElementClass, resultAssemblers.length ); + for ( int i = 0; i < resultAssemblers.length; i++ ) { + resultRow[i] = resultAssemblers[i].assemble( rowProcessingState ); } + return rowTransformer == null + ? (T) resultRow + : rowTransformer.transformRow( resultRow ); } - - finishUpRow(); - return result; } - private T readPrimitiveRow(RowProcessingState rowProcessingState) { + private Object readPrimitiveRow(RowProcessingState rowProcessingState) { // The following is ugly, but unfortunately necessary to not hurt performance. // This implementation was micro-benchmarked and discussed with Francesco Nigro, // who hinted that using this style instead of the reflective Array.getLength(), Array.set() @@ -171,61 +171,61 @@ private T readPrimitiveRow(RowProcessingState rowProcessingState) { for ( int i = 0; i < resultAssemblers.length; i++ ) { resultBooleanRow[i] = (boolean) resultAssemblers[i].assemble( rowProcessingState ); } - return (T) resultBooleanRow; + return resultBooleanRow; case BYTE: final byte[] resultByteRow = new byte[resultAssemblers.length]; for ( int i = 0; i < resultAssemblers.length; i++ ) { resultByteRow[i] = (byte) resultAssemblers[i].assemble( rowProcessingState ); } - return (T) resultByteRow; + return resultByteRow; case CHAR: final char[] resultCharRow = new char[resultAssemblers.length]; for ( int i = 0; i < resultAssemblers.length; i++ ) { resultCharRow[i] = (char) resultAssemblers[i].assemble( rowProcessingState ); } - return (T) resultCharRow; + return resultCharRow; case SHORT: final short[] resultShortRow = new short[resultAssemblers.length]; for ( int i = 0; i < resultAssemblers.length; i++ ) { resultShortRow[i] = (short) resultAssemblers[i].assemble( rowProcessingState ); } - return (T) resultShortRow; + return resultShortRow; case INT: final int[] resultIntRow = new int[resultAssemblers.length]; for ( int i = 0; i < resultAssemblers.length; i++ ) { resultIntRow[i] = (int) resultAssemblers[i].assemble( rowProcessingState ); } - return (T) resultIntRow; + return resultIntRow; case LONG: final long[] resultLongRow = new long[resultAssemblers.length]; for ( int i = 0; i < resultAssemblers.length; i++ ) { resultLongRow[i] = (long) resultAssemblers[i].assemble( rowProcessingState ); } - return (T) resultLongRow; + return resultLongRow; case FLOAT: final float[] resultFloatRow = new float[resultAssemblers.length]; for ( int i = 0; i < resultAssemblers.length; i++ ) { resultFloatRow[i] = (float) resultAssemblers[i].assemble( rowProcessingState ); } - return (T) resultFloatRow; + return resultFloatRow; case DOUBLE: final double[] resultDoubleRow = new double[resultAssemblers.length]; for ( int i = 0; i < resultAssemblers.length; i++ ) { resultDoubleRow[i] = (double) resultAssemblers[i].assemble( rowProcessingState ); } - return (T) resultDoubleRow; + return resultDoubleRow; default: throw new AssertionError( "Object should be handled specially" ); } } private void finishUpRow() { - for ( InitializerData data : initializersData ) { + for ( var data : initializersData ) { data.setState( Initializer.State.UNINITIALIZED ); } } - private void coordinateInitializers(RowProcessingState rowProcessingState) { + private void coordinateInitializers() { for ( int i = 0; i < resultInitializers.length; i++ ) { resultInitializers[i].resolveKey( resultInitializersData[i] ); } @@ -244,7 +244,7 @@ private void coordinateInitializers(RowProcessingState rowProcessingState) { @Override public void startLoading(RowProcessingState processingState) { for ( int i = 0; i < resultInitializers.length; i++ ) { - final Initializer initializer = resultInitializers[i]; + final var initializer = resultInitializers[i]; initializer.startLoading( processingState ); resultInitializersData[i] = initializer.getData( processingState ); } @@ -305,7 +305,9 @@ else if ( resultType == float[].class) { else if ( resultType == double[].class) { return DOUBLE; } - return OBJECT; + else { + return OBJECT; + } } public Class getComponentType() { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/TupleImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/TupleImpl.java index 2409c6c0d353..f11ce68c3f5c 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/TupleImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/TupleImpl.java @@ -10,7 +10,8 @@ import jakarta.persistence.Tuple; import jakarta.persistence.TupleElement; -import static org.hibernate.internal.util.type.PrimitiveWrapperHelper.getDescriptorByPrimitiveType; +import static org.hibernate.internal.util.type.PrimitiveWrapperHelper.cast; +import static org.hibernate.internal.util.type.PrimitiveWrapperHelper.isInstance; /** * Implementation of the JPA Tuple contract @@ -27,7 +28,6 @@ public TupleImpl(TupleMetadata tupleMetadata, Object[] row) { } @Override - @SuppressWarnings("unchecked") public X get(TupleElement tupleElement) { final Integer index = tupleMetadata.get( tupleElement ); if ( index == null ) { @@ -36,15 +36,14 @@ public X get(TupleElement tupleElement) { ); } // index should be "in range" by nature of size check in ctor - return (X) row[index]; + return cast( tupleElement.getJavaType(), row[index] ); } @Override - @SuppressWarnings("unchecked") public X get(String alias, Class type) { final Object untyped = get( alias ); if ( untyped != null ) { - if ( !elementTypeMatches( type, untyped ) ) { + if ( !isInstance( type, untyped ) ) { throw new IllegalArgumentException( String.format( "Requested tuple value [alias=%s, value=%s] cannot be assigned to requested type [%s]", @@ -55,12 +54,12 @@ public X get(String alias, Class type) { ); } } - return (X) untyped; + return cast( type, untyped ); } @Override public Object get(String alias) { - Integer index = tupleMetadata.get( alias ); + final Integer index = tupleMetadata.get( alias ); if ( index == null ) { throw new IllegalArgumentException( "Given alias [" + alias + "] did not correspond to an element in the result tuple" @@ -71,10 +70,9 @@ public Object get(String alias) { } @Override - @SuppressWarnings("unchecked") public X get(int i, Class type) { final Object result = get( i ); - if ( result != null && !elementTypeMatches( type, result ) ) { + if ( result != null && !isInstance( type, result ) ) { throw new IllegalArgumentException( String.format( "Requested tuple value [index=%s, realType=%s] cannot be assigned to requested type [%s]", @@ -84,7 +82,7 @@ public X get(int i, Class type) { ) ); } - return (X) result; + return cast( type, result ); } @Override @@ -97,11 +95,6 @@ public Object get(int i) { return row[i]; } - private boolean elementTypeMatches(Class type, Object untyped) { - return type.isInstance( untyped ) - || type.isPrimitive() && getDescriptorByPrimitiveType( type ).getWrapperClass().isInstance( untyped ); - } - @Override public Object[] toArray() { return row; diff --git a/hibernate-core/src/main/java/org/hibernate/usertype/UserType.java b/hibernate-core/src/main/java/org/hibernate/usertype/UserType.java index 96757961a1bf..8ecc1dd8c3af 100644 --- a/hibernate-core/src/main/java/org/hibernate/usertype/UserType.java +++ b/hibernate-core/src/main/java/org/hibernate/usertype/UserType.java @@ -448,8 +448,9 @@ default Serializable disassemble(J value) { * @see org.hibernate.Cache */ default J assemble(Serializable cached, Object owner) { - if ( returnedClass().isInstance( cached) ) { - return deepCopy( (J) cached ); + final var returnedClass = returnedClass(); + if ( returnedClass.isInstance( cached ) ) { + return deepCopy( returnedClass.cast( cached ) ); } else { throw new UnsupportedOperationException( "User-defined type '" diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/EnumType.java b/hibernate-core/src/test/java/org/hibernate/orm/test/EnumType.java index 338c44fde74f..d04760f2a4f0 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/EnumType.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/EnumType.java @@ -175,11 +175,10 @@ private boolean isNationalized(ParameterType reader) { || reader!=null && getAnnotation( reader.getAnnotationsMethod(), Nationalized.class ) != null; } - @SuppressWarnings("unchecked") private A getAnnotation(Annotation[] annotations, Class annotationType) { for ( Annotation annotation : annotations ) { if ( annotationType.isInstance( annotation ) ) { - return (A) annotation; + return annotationType.cast( annotation ); } } return null; From 074b880d1a4ac9dc79aa56cd9d5de28f4191047d Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 6 Dec 2025 23:45:44 +0100 Subject: [PATCH 03/10] slight simplification to SessionImpl.setProperty() --- .../org/hibernate/internal/SessionImpl.java | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index 9f01e1fe356d..47f6e75468e8 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -2582,24 +2582,22 @@ public LockModeType getLockMode(Object entity) { @Override public void setProperty(String propertyName, Object value) { checkOpen(); - if ( value instanceof Serializable ) { - if ( propertyName != null ) { - // store property for future reference - if ( properties == null ) { - properties = getInitialProperties(); - } - properties.put( propertyName, value ); - // now actually update the setting if - // it's one that affects this Session - interpretProperty( propertyName, value ); - } - else { - SESSION_LOGGER.nullPropertyKey(); - } + if ( propertyName == null ) { + SESSION_LOGGER.nullPropertyKey(); } - else { + else if ( !(value instanceof Serializable) ) { SESSION_LOGGER.nonSerializableProperty( propertyName ); } + else { + // store property for future reference + if ( properties == null ) { + properties = getInitialProperties(); + } + properties.put( propertyName, value ); + // now actually update the setting if + // it's one that affects this Session + interpretProperty( propertyName, value ); + } } private void interpretProperty(String propertyName, Object value) { From dfef08fb7ef9eb212c1fa232b50ddcb3627f69f6 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sun, 7 Dec 2025 00:27:59 +0100 Subject: [PATCH 04/10] attempt to make checker happy --- .../org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java | 2 +- .../org/hibernate/sql/results/internal/StandardRowReader.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java index 937e489afd3a..76f83749a12a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java @@ -146,7 +146,7 @@ protected void copyTo(AbstractSqmFrom target, SqmCopyContext context) { if ( treats != null ) { final ArrayList> newTreats = new ArrayList<>( treats.size() ); - for ( var treat : treats ) { + for ( SqmTreatedFrom treat : treats ) { newTreats.add( treat.copy( context ) ); } target.treats = newTreats; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java index 0cbefbe2b05d..4499d498a896 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java @@ -133,7 +133,6 @@ public boolean hasCollectionInitializers() { } @Override - @AllowReflection public T readRow(RowProcessingState rowProcessingState) { coordinateInitializers(); final T result = getResult( rowProcessingState ); @@ -141,6 +140,7 @@ public T readRow(RowProcessingState rowProcessingState) { return result; } + @AllowReflection @SuppressWarnings("unchecked") private T getResult(RowProcessingState rowProcessingState) { if ( componentType != ComponentType.OBJECT ) { From a9f015e40d26448221f989fc8f7fb19727751ce0 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sun, 7 Dec 2025 09:43:45 +0100 Subject: [PATCH 05/10] hack around an issue with mapping arrays of Date as SQL ARRAYs I don't know why we even need to be doing this. We deprecated that stuff. But we have one single test which is relying on this, so perhaps users are using it too. --- .../type/AbstractStandardBasicType.java | 15 ++---- .../org/hibernate/type/BasicArrayType.java | 28 ++++++++++- .../java/AbstractArrayJavaType.java | 12 +++++ .../type/descriptor/java/ArrayJavaType.java | 48 +++++++++++++++---- .../array/MySqlArrayOfTimestampsTest.java | 5 -- 5 files changed, 84 insertions(+), 24 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java index 9c6434711ef7..f3ace5a14584 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java @@ -14,7 +14,6 @@ import java.util.Map; import org.hibernate.Hibernate; -import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; import org.hibernate.engine.spi.SessionFactoryImplementor; @@ -268,21 +267,17 @@ public final boolean isMutable() { } @Override - public final Object deepCopy(Object value, SessionFactoryImplementor factory) { - return deepCopy( javaType.cast( value ) ); - } - - protected final T deepCopy(T value) { - return getMutabilityPlan().deepCopy( value ); + public Object deepCopy(Object value, SessionFactoryImplementor factory) { + return getMutabilityPlan().deepCopy( javaType.cast( value ) ); } @Override - public final Serializable disassemble(Object value, SharedSessionContractImplementor session, Object owner) throws HibernateException { - return getMutabilityPlan().disassemble( javaType.cast( value ) , session ); + public final Serializable disassemble(Object value, SharedSessionContractImplementor session, Object owner) { + return getMutabilityPlan().disassemble( javaType.cast( value ), session ); } @Override - public final Object assemble(Serializable cached, SharedSessionContractImplementor session, Object owner) throws HibernateException { + public final Object assemble(Serializable cached, SharedSessionContractImplementor session, Object owner) { return getMutabilityPlan().assemble( cached, session ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java b/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java index 963bb7b436c2..2d49dcad048e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java @@ -6,6 +6,8 @@ import java.util.Objects; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.type.descriptor.java.AbstractArrayJavaType; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; @@ -16,17 +18,19 @@ * @author Jordan Gigov * @author Christian Beikov */ -public class BasicArrayType +public final class BasicArrayType extends AbstractSingleColumnStandardBasicType implements AdjustableBasicType, BasicPluralType { private final BasicType baseDescriptor; private final String name; + private final AbstractArrayJavaType arrayTypeDescriptor; public BasicArrayType(BasicType baseDescriptor, JdbcType arrayJdbcType, JavaType arrayTypeDescriptor) { super( arrayJdbcType, arrayTypeDescriptor ); this.baseDescriptor = baseDescriptor; this.name = determineArrayTypeName( baseDescriptor ); + this.arrayTypeDescriptor = (AbstractArrayJavaType) arrayTypeDescriptor; } static String determineElementTypeName(BasicType baseDescriptor) { @@ -75,4 +79,26 @@ public boolean equals(Object object) { public int hashCode() { return baseDescriptor.hashCode(); } + + // Methods required to support Horrible hack around the fact + // that java.sql.Timestamps in an array can be represented as + // instances of java.util.Date (Why do we even allow this?) + + @Override + public boolean isEqual(Object one, Object another) { + if ( one == another ) { + return true; + } + else if ( one == null || another == null ) { + return false; + } + else { + return arrayTypeDescriptor.isEqual( one, another ); + } + } + + @Override + public Object deepCopy(Object value, SessionFactoryImplementor factory) { + return arrayTypeDescriptor.deepCopy( value ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java index d7d1207db2bd..dcb9ac7a03fa 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java @@ -19,6 +19,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; import org.hibernate.type.spi.TypeConfiguration; + import static java.lang.reflect.Array.newInstance; @AllowReflection @@ -123,4 +124,15 @@ BasicType resolveType( () -> new BasicArrayType<>( elementType, arrayJdbcType, arrayJavaType ) ); } + // Methods required to support Horrible hack around the fact + // that java.sql.Timestamps in an array can be represented as + // instances of java.util.Date (Why do we even allow this?) + + public T deepCopy(Object value) { + return getMutabilityPlan().deepCopy( cast( value ) ); + } + + public boolean isEqual(Object one, Object another) { + return areEqual( cast( one ), cast( another) ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java index 323d9312f228..a4a7098f0ae1 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java @@ -111,7 +111,7 @@ public String extractLoggableRepresentation(T[] value) { } @Override - public boolean areEqual(T[] one, T[] another) { + public boolean areEqual(Object[] one, Object[] another) { if ( one == null && another == null ) { return true; } @@ -123,7 +123,13 @@ public boolean areEqual(T[] one, T[] another) { } int l = one.length; for ( int i = 0; i < l; i++ ) { - if ( !getElementJavaType().areEqual( one[i], another[i] )) { + final var elementJavaType = getElementJavaType(); + if ( !elementJavaType.areEqual( + // Horrible hack around the fact that java.sql.Timestamps + // can be represented as instances of java.util.Date + // (Why do we even allow this? We deprecated java.sql stuff!) + elementJavaType.coerce( one[i], null ), + elementJavaType.coerce( another[i], null ) )) { return false; } } @@ -376,15 +382,36 @@ private T[] fromBytes(byte[] bytes) { } } + // Methods required to support Horrible hack around the fact + // that java.sql.Timestamps in an array can be represented as + // instances of java.util.Date (Why do we even allow this?) + + @Override + public T[] deepCopy(Object value) { + final var mutabilityPlan = + (ArrayMutabilityPlan) + super.getMutabilityPlan(); + return mutabilityPlan.deepCopy( (Object[]) value ); + } + + @Override + public boolean isEqual(Object one, Object another) { + return areEqual( (Object[]) one, (Object[]) another ); + } + @AllowReflection private static class ArrayMutabilityPlan implements MutabilityPlan { private final Class componentClass; private final MutabilityPlan componentPlan; + private final Class arrayClass; + private final JavaType baseDescriptor; public ArrayMutabilityPlan(JavaType baseDescriptor) { + this.baseDescriptor = baseDescriptor; this.componentClass = baseDescriptor.getJavaTypeClass(); this.componentPlan = baseDescriptor.getMutabilityPlan(); + this.arrayClass = arrayClass( componentClass ); } @Override @@ -393,16 +420,21 @@ public boolean isMutable() { } @Override - public T[] deepCopy(T[] value) { + public T[] deepCopy(Object[] value) { if ( value == null ) { return null; } - //noinspection unchecked - final T[] copy = (T[]) newInstance( componentClass, value.length ); - for ( int i = 0; i < value.length; i ++ ) { - copy[ i ] = componentPlan.deepCopy( value[ i ] ); + else { + final var copy = arrayClass.cast( newInstance( componentClass, value.length ) ); + for ( int i = 0; i < value.length; i++ ) { + copy[i] = componentPlan.deepCopy( + // Horrible hack around the fact that java.sql.Timestamps + // can be represented as instances of java.util.Date + // (Why do we even allow this? We deprecated java.sql stuff!) + baseDescriptor.coerce( value[i], null ) ); + } + return copy; } - return copy; } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/array/MySqlArrayOfTimestampsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/array/MySqlArrayOfTimestampsTest.java index 4829c0608978..b996924b5c67 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/array/MySqlArrayOfTimestampsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/array/MySqlArrayOfTimestampsTest.java @@ -22,7 +22,6 @@ import org.junit.jupiter.api.Test; import java.sql.Timestamp; -import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Month; import java.util.Calendar; @@ -109,10 +108,6 @@ public void testDate(SessionFactoryScope scope) { } ); } - private static final LocalDateTime SUMMER = LocalDate.of( 2024, 6, 20 ).atStartOfDay(); - private static final LocalDateTime WINTER = LocalDate.of( 2023, 12, 22 ).atStartOfDay(); - private static final LocalDate EPOCH = LocalDate.of( 1970, Month.JANUARY, 1 ); - private static final TimeZone[] TEST_TIME_ZONES = Stream.of( "Africa/Monrovia", "Europe/Zagreb", From aaf0f6b4db78fdf0d229df867876a33df99139b5 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sun, 7 Dec 2025 09:44:21 +0100 Subject: [PATCH 06/10] misc code cleanups --- .../type/AbstractStandardBasicType.java | 2 +- .../org/hibernate/type/BasicArrayType.java | 15 ++++--- .../java/JdbcTimestampJavaType.java | 44 ++++++++----------- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java index f3ace5a14584..4dca9e44c747 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java @@ -93,7 +93,7 @@ public T fromString(CharSequence string) { } protected MutabilityPlan getMutabilityPlan() { - return this.mutabilityPlan; + return mutabilityPlan; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java b/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java index 2d49dcad048e..29bda587fe0c 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java @@ -12,6 +12,8 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; +import static java.lang.Character.toUpperCase; + /** * A type that maps between {@link java.sql.Types#ARRAY ARRAY} and {@code T[]} * @@ -37,7 +39,8 @@ static String determineElementTypeName(BasicType baseDescriptor) { final String elementName = baseDescriptor.getName(); return switch ( elementName ) { case "boolean", "byte", "char", "short", "int", "long", "float", "double" -> - Character.toUpperCase( elementName.charAt( 0 ) ) + elementName.substring( 1 ); + toUpperCase( elementName.charAt( 0 ) ) + + elementName.substring( 1 ); default -> elementName; }; } @@ -63,16 +66,18 @@ protected boolean registerUnderJavaType() { @Override public BasicType resolveIndicatedType(JdbcTypeIndicators indicators, JavaType domainJtd) { - // TODO: maybe fallback to some encoding by default if the DB doesn't support arrays natively? - // also, maybe move that logic into the ArrayJdbcType + // TODO: maybe fall back to some encoding by default if + // the database doesn't support arrays natively? + // also, maybe move that logic into the ArrayJdbcType //noinspection unchecked return (BasicType) this; } @Override public boolean equals(Object object) { - return object == this || object.getClass() == BasicArrayType.class - && Objects.equals( baseDescriptor, ( (BasicArrayType) object ).baseDescriptor ); + return object == this + || object instanceof BasicArrayType arrayType // no subtypes + && Objects.equals( baseDescriptor, arrayType.baseDescriptor ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java index 2cde56adea3f..2b8f61a016e1 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java @@ -85,32 +85,26 @@ public boolean areEqual(Date one, Date another) { if ( one == another ) { return true; } - if ( one == null || another == null) { + else if ( one == null || another == null) { return false; } - - long t1 = one.getTime(); - long t2 = another.getTime(); - - boolean oneIsTimestamp = one instanceof Timestamp; - boolean anotherIsTimestamp = another instanceof Timestamp; - - int n1 = oneIsTimestamp ? ( (Timestamp) one ).getNanos() : 0; - int n2 = anotherIsTimestamp ? ( (Timestamp) another ).getNanos() : 0; - - if ( t1 != t2 ) { - return false; - } - - if ( oneIsTimestamp && anotherIsTimestamp ) { - // both are Timestamps - int nn1 = n1 % 1000000; - int nn2 = n2 % 1000000; - return nn1 == nn2; - } else { - // at least one is a plain old Date - return true; + final long t1 = one.getTime(); + final long t2 = another.getTime(); + if ( t1 != t2 ) { + return false; + } + else if ( one instanceof Timestamp ts1 + && another instanceof Timestamp ts2 ) { + // both are Timestamps + final int nn1 = ts1.getNanos() % 1000000; + final int nn2 = ts2.getNanos() % 1000000; + return nn1 == nn2; + } + else { + // at least one is a plain old Date + return true; + } } } @@ -132,8 +126,8 @@ public Object unwrap(Date value, Class type, WrapperOptions options) { } if ( Timestamp.class.isAssignableFrom( type ) ) { - return value instanceof Timestamp - ? (Timestamp) value + return value instanceof Timestamp timestamp + ? timestamp : new Timestamp( value.getTime() ); } From 15a4b3d194e0fef866c85f88ea5f7e0692849e5c Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sun, 7 Dec 2025 11:08:09 +0100 Subject: [PATCH 07/10] fix up a bunch more unchecked casts --- .../ValueBindJpaCriteriaParameter.java | 39 +++++--- .../converter/internal/ArrayConverter.java | 68 ++++++------- .../java/AbstractArrayJavaType.java | 8 +- .../type/descriptor/java/ArrayJavaType.java | 97 +++++++++++-------- .../descriptor/java/ArrayMutabilityPlan.java | 25 ++--- .../type/descriptor/java/EnumJavaType.java | 3 +- 6 files changed, 131 insertions(+), 109 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/ValueBindJpaCriteriaParameter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/ValueBindJpaCriteriaParameter.java index 6562bde5dd45..89736c09f9c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/ValueBindJpaCriteriaParameter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/ValueBindJpaCriteriaParameter.java @@ -40,7 +40,7 @@ private ValueBindJpaCriteriaParameter(ValueBindJpaCriteriaParameter original) @Override public ValueBindJpaCriteriaParameter copy(SqmCopyContext context) { - final ValueBindJpaCriteriaParameter existing = context.getCopy( this ); + final var existing = context.getCopy( this ); return existing != null ? existing : context.registerCopy( this, new ValueBindJpaCriteriaParameter<>( this ) ); @@ -59,26 +59,31 @@ public void appendHqlString(StringBuilder hql, SqmRenderContext context) { // but for equals/hashCode, use equals/hashCode of the underlying value, if available, from the nodes JavaType @Override - public final boolean equals(@Nullable Object o) { - if ( this == o ) { + public final boolean equals(@Nullable Object object) { + if ( this == object ) { return true; } - if ( o instanceof ValueBindJpaCriteriaParameter that ) { - if ( value == null ) { - return that.value == null && Objects.equals( getNodeType(), that.getNodeType() ); + else if ( object instanceof ValueBindJpaCriteriaParameter that ) { + if ( this.value == null || that.value == null ) { + return this.value == that.value + && Objects.equals( this.getNodeType(), that.getNodeType() ); } - final var javaType = getJavaTypeDescriptor(); - if ( that.value != null ) { - if ( javaType != null ) { - //noinspection unchecked - return javaType.equals( that.getJavaTypeDescriptor() ) && javaType.areEqual( value, (T) that.value ); + else { + final var thisJavaType = getJavaTypeDescriptor(); + final var thatJavaType = that.getJavaTypeDescriptor(); + if ( thisJavaType == null || thatJavaType == null ) { + return thisJavaType == thatJavaType + && this.value.equals( that.value ); } else { - return that.getJavaTypeDescriptor() == null && value.equals( that.value ); + return thisJavaType.equals( thatJavaType ) + && thisJavaType.areEqual( value, thisJavaType.cast( that.value ) ); } } } - return false; + else { + return false; + } } @Override @@ -86,7 +91,11 @@ public int hashCode() { if ( value == null ) { return 0; } - final var javaType = getJavaTypeDescriptor(); - return javaType == null ? value.hashCode() : javaType.extractHashCode( value ); + else { + final var javaType = getJavaTypeDescriptor(); + return javaType == null + ? value.hashCode() + : javaType.extractHashCode( value ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/ArrayConverter.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/ArrayConverter.java index 0b7076ee3f47..715406a406df 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/ArrayConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/ArrayConverter.java @@ -4,93 +4,87 @@ */ package org.hibernate.type.descriptor.converter.internal; -import java.lang.reflect.Array; - import org.hibernate.internal.build.AllowReflection; +import org.hibernate.type.BasicType; import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; import org.hibernate.type.descriptor.java.JavaType; +import static java.lang.reflect.Array.newInstance; +import static org.hibernate.internal.util.ReflectHelper.arrayClass; + /** * Given a {@link BasicValueConverter} for array elements, handles conversion * to and from an array of the converted element type. * * @param the unconverted element type * @param the converted element type - * @param the unconverted array type - * @param the converted array type + * @param the unconverted array type (same as {@code E[]}) */ @AllowReflection -public class ArrayConverter implements BasicValueConverter { +public class ArrayConverter implements BasicValueConverter { private final BasicValueConverter elementConverter; private final JavaType domainJavaType; - private final JavaType relationalJavaType; + private final JavaType relationalJavaType; + private final Class arrayClass; public ArrayConverter( BasicValueConverter elementConverter, JavaType domainJavaType, - JavaType relationalJavaType) { + JavaType relationalJavaType, + BasicType elementType) { this.elementConverter = elementConverter; this.domainJavaType = domainJavaType; this.relationalJavaType = relationalJavaType; + this.arrayClass = arrayClass( elementType.getJavaType() ); } @Override - public T toDomainValue(S relationalForm) { + public T toDomainValue(F[] relationalForm) { if ( relationalForm == null ) { return null; } else { - final Class elementClass = elementConverter.getDomainJavaType().getJavaTypeClass(); - if ( relationalForm.getClass().getComponentType() == elementClass) { - //noinspection unchecked - return (T) relationalForm; - } - else { - //noinspection unchecked - return convertTo( (F[]) relationalForm, elementClass ); - } + final var elementClass = + elementConverter.getDomainJavaType().getJavaTypeClass(); + return relationalForm.getClass().getComponentType() == elementClass + ? domainJavaType.cast( relationalForm ) + : convertTo( relationalJavaType.cast( relationalForm ), elementClass ); } } private T convertTo(F[] relationalArray, Class elementClass) { //TODO: the following implementation only handles conversion between non-primitive arrays! - //noinspection unchecked - final E[] domainArray = (E[]) Array.newInstance( elementClass, relationalArray.length ); + final var domainArray = + arrayClass.cast( newInstance( elementClass, relationalArray.length ) ); for ( int i = 0; i < relationalArray.length; i++ ) { domainArray[i] = elementConverter.toDomainValue( relationalArray[i] ); } - //noinspection unchecked - return (T) domainArray; + return domainJavaType.cast( domainArray ); } @Override - public S toRelationalValue(T domainForm) { + public F[] toRelationalValue(T domainForm) { if ( domainForm == null ) { return null; } else { - final Class elementClass = elementConverter.getRelationalJavaType().getJavaTypeClass(); - if ( domainForm.getClass().getComponentType() == elementClass) { - //noinspection unchecked - return (S) domainForm; - } - else { - //noinspection unchecked - return convertFrom((E[]) domainForm, elementClass); - } + final Class elementClass = + elementConverter.getRelationalJavaType().getJavaTypeClass(); + return domainForm.getClass().getComponentType() == elementClass + ? relationalJavaType.cast( domainForm ) + : convertFrom( arrayClass.cast( domainForm ), elementClass ); } } - private S convertFrom(E[] domainArray, Class elementClass) { + private F[] convertFrom(E[] domainArray, Class elementClass) { //TODO: the following implementation only handles conversion between non-primitive arrays! - //noinspection unchecked - final F[] relationalArray = (F[]) Array.newInstance( elementClass, domainArray.length ); + final var relationalArray = + relationalJavaType.cast( newInstance( elementClass, domainArray.length ) ); for ( int i = 0; i < domainArray.length; i++ ) { relationalArray[i] = elementConverter.toRelationalValue( domainArray[i] ); } - //noinspection unchecked - return (S) relationalArray; + return relationalArray; } @Override @@ -99,7 +93,7 @@ public JavaType getDomainJavaType() { } @Override - public JavaType getRelationalJavaType() { + public JavaType getRelationalJavaType() { return relationalJavaType; } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java index dcb9ac7a03fa..3a2fb269d8d7 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java @@ -20,7 +20,7 @@ import org.hibernate.type.spi.TypeConfiguration; -import static java.lang.reflect.Array.newInstance; +import static org.hibernate.internal.util.ReflectHelper.arrayClass; @AllowReflection public abstract class AbstractArrayJavaType extends AbstractClassJavaType @@ -98,8 +98,8 @@ BasicType createTypeUsingConverter( ColumnTypeInformation columnTypeInformation, JdbcTypeIndicators indicators, BasicValueConverter valueConverter) { - final var convertedElementClass = valueConverter.getRelationalJavaType().getJavaTypeClass(); - final var convertedArrayClass = newInstance( convertedElementClass, 0 ).getClass(); + final var convertedArrayClass = + arrayClass( valueConverter.getRelationalJavaType().getJavaTypeClass() ); final var relationalJavaType = typeConfiguration.getJavaTypeRegistry() .resolveDescriptor( convertedArrayClass ); @@ -107,7 +107,7 @@ BasicType createTypeUsingConverter( elementType, arrayJdbcType( typeConfiguration, elementType, columnTypeInformation, indicators ), this, - new ArrayConverter<>( valueConverter, this, relationalJavaType ) + new ArrayConverter<>( valueConverter, this, relationalJavaType, elementType ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java index a4a7098f0ae1..8010b895a3b4 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java @@ -299,52 +299,71 @@ public T[] wrap(X value, WrapperOptions options) { } } - final var elementJavaType = getElementJavaType(); - if ( value instanceof Object[] raw ) { - final var componentClass = elementJavaType.getJavaTypeClass(); - //noinspection unchecked - final var wrapped = (T[]) newInstance( componentClass, raw.length ); - if ( componentClass.isAssignableFrom( value.getClass().getComponentType() ) ) { - for (int i = 0; i < raw.length; i++) { - //noinspection unchecked - wrapped[i] = (T) raw[i]; - } - } - else { - for ( int i = 0; i < raw.length; i++ ) { - wrapped[i] = elementJavaType.wrap( raw[i], options ); - } - } - return wrapped; + if ( value instanceof Object[] array ) { + return wrapObjectArray( value, array, options ); } else if ( value instanceof byte[] bytes ) { return fromBytes( bytes ); } else if ( value instanceof BinaryStream binaryStream ) { - // When the value is a BinaryStream, this is a deserialization request + // When the value is a BinaryStream, + // this is a deserialization request return fromBytes( binaryStream.getBytes() ); } - else if ( elementJavaType.isInstance( value ) ) { - // Support binding a single element as parameter value - //noinspection unchecked - final var wrapped = (T[]) newInstance( elementJavaType.getJavaTypeClass(), 1 ); - //noinspection unchecked - wrapped[0] = (T) value; - return wrapped; - } else if ( value instanceof Collection collection ) { - //noinspection unchecked - final var wrapped = (T[]) newInstance( elementJavaType.getJavaTypeClass(), collection.size() ); - int i = 0; - for ( Object e : collection ) { - wrapped[i++] = elementJavaType.wrap( e, options ); - } - return wrapped; + return wrapCollection( collection, options ); + } + else if ( getElementJavaType().isInstance( value ) ) { + // Support binding a single element as a parameter value + return wrapSingleElement( value, options ); } throw unknownWrap( value.getClass() ); } + private T[] wrapCollection(Collection collection, WrapperOptions options) { + final var arrayClass = getJavaTypeClass(); + final var elementJavaType = getElementJavaType(); + final var wrapped = newArray( arrayClass, elementJavaType, collection.size() ); + int i = 0; + for ( Object element : collection ) { + wrapped[i++] = elementJavaType.wrap( element, options ); + } + return wrapped; + } + + private < X> T[] wrapSingleElement(X value, WrapperOptions options) { + final var arrayClass = getJavaTypeClass(); + final var elementJavaType = getElementJavaType(); + final var wrapped = newArray( arrayClass, elementJavaType, 1 ); + wrapped[0] = elementJavaType.wrap( value, options ); + return wrapped; + } + + private T[] wrapObjectArray(X value, Object[] array, WrapperOptions options) { + final var arrayClass = getJavaTypeClass(); + final var elementJavaType = getElementJavaType(); + final var wrapped = newArray( arrayClass, elementJavaType, array.length ); + // I suppose this code was there as an optimization, + // but it doesn't really look necessary to me +// if ( elementJavaType.getJavaTypeClass() +// .isAssignableFrom( value.getClass().getComponentType() ) ) { +// for ( int i = 0; i < array.length; i++) { +// wrapped[i] = elementJavaType.cast( array[i] ); +// } +// } +// else { + for ( int i = 0; i < array.length; i++ ) { + wrapped[i] = elementJavaType.wrap( array[i], options ); + } +// } + return wrapped; + } + + private static T[] newArray(Class arrayClass, JavaType elementJavaType, int length) { + return arrayClass.cast( newInstance( elementJavaType.getJavaTypeClass(), length ) ); + } + private static byte[] toBytes(T[] array) { if ( array.getClass().getComponentType().isEnum() ) { final byte[] bytes = new byte[array.length]; @@ -364,21 +383,19 @@ private static byte[] toBytes(T[] array) { private T[] fromBytes(byte[] bytes) { final var elementClass = getElementJavaType().getJavaTypeClass(); + final var arrayClass = getJavaTypeClass(); if ( elementClass.isEnum() ) { - final T[] enumConstants = elementClass.getEnumConstants(); - final var array = (Object[]) newInstance( elementClass, bytes.length ); + final var enumConstants = elementClass.getEnumConstants(); + final var array = newArray( arrayClass, getElementJavaType(), bytes.length ); for (int i = 0; i < bytes.length; i++ ) { // null enum value was encoded as -1 array[i] = bytes[i] == -1 ? null : enumConstants[bytes[i]]; } - //noinspection unchecked - return (T[]) array; - + return array; } else { // When the value is a byte[], this is a deserialization request - //noinspection unchecked - return (T[]) SerializationHelper.deserialize(bytes); + return arrayClass.cast( SerializationHelper.deserialize( bytes ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayMutabilityPlan.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayMutabilityPlan.java index 0298aff86f0d..6dddd6a5dcb0 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayMutabilityPlan.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayMutabilityPlan.java @@ -3,34 +3,37 @@ * Copyright Red Hat Inc. and Hibernate Authors */ package org.hibernate.type.descriptor.java; + import org.hibernate.internal.build.AllowReflection; -import java.lang.reflect.Array; +import static java.lang.reflect.Array.getLength; +import static java.lang.reflect.Array.newInstance; /** - * A mutability plan for arrays. Specifically arrays of immutable element type; since the elements themselves - * are immutable, a shallow copy is enough. + * A mutability plan for arrays. Specifically arrays of immutable element type; + * since the elements themselves are immutable, a shallow copy is enough. * * @author Steve Ebersole * * @deprecated Use {@link ImmutableObjectArrayMutabilityPlan#get()} for object arrays, - * or implement a dedicated mutability plan for primitive arrays - * (see for example {@link ShortPrimitiveArrayJavaType}'s mutability plan). + * or implement a dedicated mutability plan for primitive arrays + * (see for example {@link ShortPrimitiveArrayJavaType}'s mutability plan). */ -@Deprecated +@Deprecated(forRemoval = true, since = "7.0") public class ArrayMutabilityPlan extends MutableMutabilityPlan { public static final ArrayMutabilityPlan INSTANCE = new ArrayMutabilityPlan(); @SuppressWarnings({ "unchecked", "SuspiciousSystemArraycopy" }) @AllowReflection public T deepCopyNotNull(T value) { - if ( ! value.getClass().isArray() ) { + final var valueClass = value.getClass(); + if ( !valueClass.isArray() ) { // ugh! cannot find a way to properly define the type signature here - throw new IllegalArgumentException( "Value was not an array [" + value.getClass().getName() + "]" ); + throw new IllegalArgumentException( "Value was not an array [" + valueClass.getName() + "]" ); } - final int length = Array.getLength( value ); - T copy = (T) Array.newInstance( value.getClass().getComponentType(), length ); + final int length = getLength( value ); + final Object copy = newInstance( valueClass.getComponentType(), length ); System.arraycopy( value, 0, copy, 0, length ); - return copy; + return (T) copy; } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java index 4e33a9875fb8..60241c28889f 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java @@ -116,7 +116,6 @@ else if ( Byte.class.equals( type ) ) { } @Override - @SuppressWarnings("unchecked") public T wrap(X value, WrapperOptions options) { if ( value == null ) { return null; @@ -140,7 +139,7 @@ else if ( value instanceof Number number ) { return fromLong( number.longValue() ); } else { - return (T) value; + return cast( value ); } } From b2ed4c5f043b64f54689d98474198a6f6f0e0bb7 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sun, 7 Dec 2025 11:21:28 +0100 Subject: [PATCH 08/10] work around a design problem (possibly a bug) affecting hibernate-vector --- .../org/hibernate/type/BasicArrayType.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java b/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java index 29bda587fe0c..13502e29806b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java @@ -32,7 +32,13 @@ public BasicArrayType(BasicType baseDescriptor, JdbcType arrayJdbcType, JavaT super( arrayJdbcType, arrayTypeDescriptor ); this.baseDescriptor = baseDescriptor; this.name = determineArrayTypeName( baseDescriptor ); - this.arrayTypeDescriptor = (AbstractArrayJavaType) arrayTypeDescriptor; + this.arrayTypeDescriptor = + arrayTypeDescriptor instanceof AbstractArrayJavaType arrayJavaType + ? arrayJavaType + // this only happens with contributions from hibernate-vector + // because it passes in a PrimitiveByteArrayJavaType which is + // not an AbstractArrayJavaType (this might be a bug) + : null; } static String determineElementTypeName(BasicType baseDescriptor) { @@ -91,7 +97,11 @@ public int hashCode() { @Override public boolean isEqual(Object one, Object another) { - if ( one == another ) { + if ( arrayTypeDescriptor == null ) { + // for hibernate-vector + return super.isEqual( one, another ); + } + else if ( one == another ) { return true; } else if ( one == null || another == null ) { @@ -104,6 +114,8 @@ else if ( one == null || another == null ) { @Override public Object deepCopy(Object value, SessionFactoryImplementor factory) { - return arrayTypeDescriptor.deepCopy( value ); + return arrayTypeDescriptor == null + ? super.deepCopy( value, factory ) // for hibernate-vector + : arrayTypeDescriptor.deepCopy( value ); } } From d05f048c8424dcb7d9b8a55e4d492b0ffcfc2bbe Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sun, 7 Dec 2025 12:31:57 +0100 Subject: [PATCH 09/10] deprecate the unsafe methods of JpaMetamodel and fix unchecked casts in the impl --- .../metamodel/model/domain/JpaMetamodel.java | 12 +++++ .../domain/internal/JpaMetamodelImpl.java | 49 ++++++++++++------- .../domain/internal/MappingMetamodelImpl.java | 8 +-- .../internal/BasicDotIdentifierConsumer.java | 1 + .../internal/QualifiedJoinPathConsumer.java | 8 +-- .../hql/internal/SemanticQueryBuilder.java | 9 ++-- .../internal/EmbeddableFetchImpl.java | 8 ++- 7 files changed, 64 insertions(+), 31 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java index ca496516c904..9a9c6e98423a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java @@ -33,7 +33,10 @@ public interface JpaMetamodel extends Metamodel { /** * Access to a managed type through its name + * + * @deprecated This method performs an unchecked type cast */ + @Deprecated(since = "7.2") ManagedDomainType managedType(String typeName); /** @@ -49,13 +52,19 @@ public interface JpaMetamodel extends Metamodel { /** * Specialized handling for resolving entity-name references in * an HQL query + * + * @deprecated This method performs an unchecked type cast */ + @Deprecated(since = "7.2") EntityDomainType getHqlEntityReference(String entityName); /** * Specialized handling for resolving entity-name references in * an HQL query + * + * @deprecated This method performs an unchecked type cast */ + @Deprecated(since = "7.2") EntityDomainType resolveHqlEntityReference(String entityName); /** @@ -79,7 +88,10 @@ public interface JpaMetamodel extends Metamodel { /** * Same as {@link #managedType(String)} except {@code null} is returned rather * than throwing an exception + * + * @deprecated This method performs an unchecked type cast */ + @Deprecated(since = "7.2") @Nullable ManagedDomainType findManagedType(@Nullable String typeName); /** diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java index 410ae933c825..c0694990ba70 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java @@ -14,6 +14,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; @@ -115,7 +116,7 @@ public ServiceRegistry getServiceRegistry() { return serviceRegistry; } - @Override + @Override @Deprecated public @Nullable ManagedDomainType findManagedType(@Nullable String typeName) { //noinspection unchecked return typeName == null ? null : (ManagedDomainType) managedTypeByName.get( typeName ); @@ -192,9 +193,10 @@ public EmbeddableDomainType embeddable(String embeddableName) { return embeddableType; } - @Override + @Override @Deprecated public EntityDomainType getHqlEntityReference(String entityName) { Class loadedClass = null; + //noinspection unchecked final var importInfo = (ImportInfo) resolveImport( entityName ); if ( importInfo != null ) { loadedClass = importInfo.loadedClass; @@ -208,6 +210,7 @@ public EntityDomainType getHqlEntityReference(String entityName) { } if ( loadedClass == null ) { + //noinspection unchecked loadedClass = (Class) resolveRequestedClass( entityName ); // populate the class cache for boot metamodel imports if ( importInfo != null && loadedClass != null ) { @@ -220,7 +223,7 @@ public EntityDomainType getHqlEntityReference(String entityName) { return null; } - @Override + @Override @Deprecated public EntityDomainType resolveHqlEntityReference(String entityName) { final EntityDomainType hqlEntityReference = getHqlEntityReference( entityName ); if ( hqlEntityReference == null ) { @@ -229,11 +232,22 @@ public EntityDomainType resolveHqlEntityReference(String entityName) { return hqlEntityReference; } + private static ManagedDomainType checkDomainType(Class cls, ManagedDomainType domainType) { + if ( domainType != null && !Objects.equals( domainType.getJavaType(), cls ) ) { + throw new IllegalStateException( "Managed type " + domainType + + " has a different Java type than requested" ); + } + else { + @SuppressWarnings("unchecked") // Safe, we checked it + final var type = (ManagedDomainType) domainType; + return type; + } + } + @Override @Nullable public ManagedDomainType findManagedType(Class cls) { - //noinspection unchecked - return (ManagedDomainType) managedTypeByClass.get( cls ); + return checkDomainType( cls, managedTypeByClass.get( cls ) ); } @Override @@ -249,10 +263,9 @@ public ManagedDomainType managedType(Class cls) { @Override @Nullable public EntityDomainType findEntityType(Class cls) { - final var type = managedTypeByClass.get( cls ); - //noinspection unchecked - return type instanceof EntityDomainType - ? (EntityDomainType) type + return checkDomainType( cls, managedTypeByClass.get( cls ) ) + instanceof EntityDomainType entityDomainType + ? entityDomainType : null; } @@ -267,10 +280,9 @@ public EntityDomainType entity(Class cls) { @Override public @Nullable EmbeddableDomainType findEmbeddableType(Class cls) { - final var type = managedTypeByClass.get( cls ); - //noinspection unchecked - return type instanceof EmbeddableDomainType - ? (EmbeddableDomainType) type + return checkDomainType( cls, managedTypeByClass.get( cls ) ) + instanceof EmbeddableDomainType embeddableDomainType + ? embeddableDomainType : null; } @@ -740,17 +752,20 @@ private EntityTypeImpl entityType( final var supertype = (IdentifiableDomainType) supertypeForPersistentClass( persistentClass, context, typeConfiguration ); - final JavaType javaType; + return new EntityTypeImpl<>( entityJavaType( mappedClass, context ), + supertype, persistentClass, this ); + } + + private static JavaType entityJavaType(Class mappedClass, MetadataContext context) { if ( mappedClass == null || Map.class.isAssignableFrom( mappedClass ) ) { // dynamic map //noinspection unchecked - javaType = (JavaType) new DynamicModelJavaType(); + return (JavaType) new DynamicModelJavaType(); } else { - javaType = context.getTypeConfiguration().getJavaTypeRegistry() + return context.getTypeConfiguration().getJavaTypeRegistry() .resolveEntityTypeDescriptor( mappedClass ); } - return new EntityTypeImpl<>( javaType, supertype, persistentClass, this ); } private void handleUnusedMappedSuperclasses(MetadataContext context, TypeConfiguration typeConfiguration) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java index 33209e400641..a5c20d424709 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java @@ -418,12 +418,12 @@ public Set> getEmbeddables() { return jpaMetamodel.getEmbeddables(); } - @Override + @Override @Deprecated public @Nullable ManagedDomainType findManagedType(@Nullable String typeName) { return jpaMetamodel.findManagedType( typeName ); } - @Override + @Override @Deprecated public ManagedDomainType managedType(String typeName) { return jpaMetamodel.managedType( typeName ); } @@ -448,12 +448,12 @@ public EmbeddableDomainType embeddable(String embeddableName) { return jpaMetamodel.embeddable( embeddableName ); } - @Override + @Override @Deprecated public EntityDomainType getHqlEntityReference(String entityName) { return jpaMetamodel.getHqlEntityReference( entityName ); } - @Override + @Override @Deprecated public EntityDomainType resolveHqlEntityReference(String entityName) { return jpaMetamodel.resolveHqlEntityReference( entityName ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java index 1cd1d5d0e2ac..0d1ad4d88b6b 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java @@ -99,6 +99,7 @@ public void consumeTreat(String importableName, boolean isTerminal) { private Class treatTarget(String typeName) { final ManagedDomainType managedType = creationState.getCreationContext().getJpaMetamodel() + // TODO: don't use this unsafe, deprecated method .managedType( typeName ); return managedType.getJavaType(); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/QualifiedJoinPathConsumer.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/QualifiedJoinPathConsumer.java index 7f2e838a6067..5f013adb41dc 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/QualifiedJoinPathConsumer.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/QualifiedJoinPathConsumer.java @@ -308,9 +308,11 @@ public void consumeTreat(String typeName, boolean isTerminal) { } private Class treatTarget(String typeName) { - final ManagedDomainType managedType = creationState.getCreationContext() - .getJpaMetamodel() - .managedType( typeName ); + final ManagedDomainType managedType = + creationState.getCreationContext() + .getJpaMetamodel() + // TODO: don't use this unsafe, deprecated method + .managedType( typeName ); return managedType.getJavaType(); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java index 2e721a911f52..7dfe199268ee 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java @@ -2138,9 +2138,8 @@ public final SqmCrossJoin visitCrossJoin(HqlParser.CrossJoinContext ctx) { protected void consumeCrossJoin(HqlParser.CrossJoinContext parserJoin, SqmRoot sqmRoot) { final String name = getEntityName( parserJoin.entityName() ); -// SqmTreeCreationLogger.LOGGER.tracef( "Handling root path - %s", name ); - - final var entityDescriptor = getJpaMetamodel().resolveHqlEntityReference( name ); + final EntityDomainType entityDescriptor = + getJpaMetamodel().resolveHqlEntityReference( name ); if ( entityDescriptor instanceof SqmPolymorphicRootDescriptor ) { throw new SemanticException( "Unmapped polymorphic reference cannot be used as a target of 'cross join'", @@ -2579,8 +2578,8 @@ else if ( r instanceof AnyDiscriminatorSqmPath anyDiscriminatorPath && l inst ); } - private SqmExpression createDiscriminatorValue( - AnyDiscriminatorSqmPath anyDiscriminatorTypeSqmPath, + private SqmExpression createDiscriminatorValue( + AnyDiscriminatorSqmPath anyDiscriminatorTypeSqmPath, HqlParser.ExpressionContext valueExpressionContext) { final var expressible = anyDiscriminatorTypeSqmPath.getExpressible(); return new SqmAnyDiscriminatorValue<>( diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java index 23445bb15838..116f068bf3dc 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java @@ -11,6 +11,7 @@ import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.model.domain.JpaMetamodel; +import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.ast.SqlAstJoinType; import org.hibernate.sql.ast.tree.expression.Expression; @@ -195,8 +196,11 @@ public EmbeddableInitializer createInitializer(InitializerParent parent, A @Override public boolean appliesTo(GraphImplementor graphImplementor, JpaMetamodel metamodel) { - // We use managedType here since this fetch could correspond to an entity type if the embeddable is an id-class - return GraphHelper.appliesTo( graphImplementor, metamodel.managedType( getResultJavaType().getTypeName() ) ); + // We use managedType here since this fetch could correspond + // to an entity type if the embeddable is an @IdClass + final ManagedDomainType managedType = + metamodel.managedType( getResultJavaType().getTypeName() ); + return GraphHelper.appliesTo( graphImplementor, managedType ); } @Override From 4bc00b64cc6f2643f955f19f458daccd3e464fe3 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sun, 7 Dec 2025 14:53:49 +0100 Subject: [PATCH 10/10] actually fix up the unsafe methods of JpaMetamodel this change exposed multiple bugs! 1. generic attributes declared by a mapped superclass where not being handled properly in HQL path expressions 2. getSubTypes() on EntityTypeImpl was broken (due, again, to use of unchecked cast!) causing problems in HQL --- .../InFlightMetadataCollectorImpl.java | 2 +- .../model/internal/ClassPropertyHolder.java | 35 ++++++------- .../metamodel/internal/AttributeFactory.java | 2 +- .../metamodel/model/domain/JpaMetamodel.java | 20 ++------ .../internal/AbstractIdentifiableType.java | 38 +++++++------- .../domain/internal/DomainModelHelper.java | 13 +++-- .../domain/internal/EmbeddableTypeImpl.java | 22 ++++++-- .../model/domain/internal/EntityTypeImpl.java | 37 ++++++++++---- .../domain/internal/JpaMetamodelImpl.java | 50 +++++++++---------- .../internal/MappedSuperclassTypeImpl.java | 2 +- .../domain/internal/MappingMetamodelImpl.java | 20 ++++---- .../internal/BasicDotIdentifierConsumer.java | 20 ++++---- .../internal/QualifiedJoinPathConsumer.java | 50 ++++++++++++------- .../hql/internal/SemanticQueryBuilder.java | 3 +- .../hibernate/query/sqm/SqmPathSource.java | 2 +- .../query/sqm/internal/TypecheckUtil.java | 2 +- .../internal/EmbeddableFetchImpl.java | 6 +-- .../validation/MockSessionFactory.java | 4 +- 18 files changed, 177 insertions(+), 151 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java index 186fbb1da563..052109c1767d 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java @@ -1767,7 +1767,7 @@ private void processValueResolvers(MetadataBuildingContext buildingContext) { private void processSecondPasses(ArrayList secondPasses) { if ( secondPasses != null ) { - for ( SecondPass secondPass : secondPasses ) { + for ( var secondPass : secondPasses ) { secondPass.doSecondPass( getEntityBindingMap() ); } secondPasses.clear(); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/ClassPropertyHolder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/ClassPropertyHolder.java index 2ec9461d3656..413c478f4d56 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/ClassPropertyHolder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/ClassPropertyHolder.java @@ -12,7 +12,6 @@ import org.hibernate.AssertionFailure; import org.hibernate.PropertyNotFoundException; import org.hibernate.boot.spi.MetadataBuildingContext; -import org.hibernate.boot.spi.SecondPass; import org.hibernate.mapping.Collection; import org.hibernate.mapping.Component; import org.hibernate.mapping.IndexedCollection; @@ -312,29 +311,25 @@ static void prepareActualProperty( if ( !allowCollections ) { throw new AssertionFailure( "Collections are not allowed as identifier properties" ); } - // The owner is a MappedSuperclass which is not a PersistentClass, so set it to null -// collection.setOwner( null ); + // The owner is a MappedSuperclass, not a PersistentClass, + // so set it to null collection.setOwner( null ); collection.setRole( memberDetails.getDeclaringType().getName() + "." + property.getName() ); // To copy the element and key values, we need to defer setting the type name until the CollectionBinder ran final var originalValue = property.getValue(); - context.getMetadataCollector().addSecondPass( - new SecondPass() { - @Override - public void doSecondPass(Map persistentClasses) { - final var initializedCollection = (Collection) originalValue; - final var element = initializedCollection.getElement().copy(); - setTypeName( element, memberDetails.getElementType().getName() ); - if ( initializedCollection instanceof IndexedCollection indexedCollection ) { - final var index = indexedCollection.getIndex().copy(); - if ( memberDetails.getMapKeyType() != null ) { - setTypeName( index, memberDetails.getMapKeyType().getName() ); - } - ( (IndexedCollection) collection ).setIndex( index ); - } - collection.setElement( element ); - } + context.getMetadataCollector().addSecondPass( persistentClasses -> { + final var initializedCollection = (Collection) originalValue; + final var element = initializedCollection.getElement().copy(); + setTypeName( element, memberDetails.getElementType().getName() ); + if ( initializedCollection instanceof IndexedCollection indexedCollection ) { + final var index = indexedCollection.getIndex().copy(); + final var mapKeyType = memberDetails.getMapKeyType(); + if ( mapKeyType != null ) { + setTypeName( index, mapKeyType.getName() ); } - ); + ( (IndexedCollection) collection ).setIndex( index ); + } + collection.setElement( element ); + } ); } else { setTypeName( value, memberDetails.getType().getName() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java index 9277ea7e1098..8c43a2cebed6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java @@ -212,7 +212,7 @@ private DomainType determineSimpleType(ValueContext typeContext) { public static DomainType determineSimpleType(ValueContext typeContext, MetadataContext context) { return switch ( typeContext.getValueClassification() ) { case BASIC -> basicDomainType( typeContext, context ); - case ENTITY -> entityDomainType (typeContext, context ); + case ENTITY -> entityDomainType( typeContext, context ); case EMBEDDABLE -> embeddableDomainType( typeContext, context ); default -> throw new AssertionFailure( "Unknown type : " + typeContext.getValueClassification() ); }; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java index 9a9c6e98423a..2d0b9166c5f8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java @@ -33,11 +33,8 @@ public interface JpaMetamodel extends Metamodel { /** * Access to a managed type through its name - * - * @deprecated This method performs an unchecked type cast */ - @Deprecated(since = "7.2") - ManagedDomainType managedType(String typeName); + ManagedDomainType managedType(String typeName); /** * Access to an entity supporting Hibernate's entity-name feature @@ -52,20 +49,14 @@ public interface JpaMetamodel extends Metamodel { /** * Specialized handling for resolving entity-name references in * an HQL query - * - * @deprecated This method performs an unchecked type cast */ - @Deprecated(since = "7.2") - EntityDomainType getHqlEntityReference(String entityName); + EntityDomainType getHqlEntityReference(String entityName); /** * Specialized handling for resolving entity-name references in * an HQL query - * - * @deprecated This method performs an unchecked type cast */ - @Deprecated(since = "7.2") - EntityDomainType resolveHqlEntityReference(String entityName); + EntityDomainType resolveHqlEntityReference(String entityName); /** * Same as {@link #managedType(Class)} except {@code null} is returned rather @@ -88,11 +79,8 @@ public interface JpaMetamodel extends Metamodel { /** * Same as {@link #managedType(String)} except {@code null} is returned rather * than throwing an exception - * - * @deprecated This method performs an unchecked type cast */ - @Deprecated(since = "7.2") - @Nullable ManagedDomainType findManagedType(@Nullable String typeName); + @Nullable ManagedDomainType findManagedType(@Nullable String typeName); /** * Same as {@link #entity(String)} except {@code null} is returned rather diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractIdentifiableType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractIdentifiableType.java index e3edd41e03c2..6b423d5c2d04 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractIdentifiableType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractIdentifiableType.java @@ -114,14 +114,15 @@ public boolean hasSingleIdAttribute() { } @Override - @SuppressWarnings("unchecked") public SqmSingularPersistentAttribute getId(Class javaType) { ensureNoIdClass(); final var id = findIdAttribute(); if ( id != null ) { checkType( id, javaType ); } - return (SqmSingularPersistentAttribute) id; + @SuppressWarnings("unchecked") // safe, we just checked + final var castId = (SqmSingularPersistentAttribute) id; + return castId; } private void ensureNoIdClass() { @@ -148,8 +149,7 @@ else if ( getSuperType() != null ) { private void checkType(SingularPersistentAttribute attribute, Class javaType) { if ( !javaType.isAssignableFrom( attribute.getType().getJavaType() ) ) { - final JavaType attributeJavaType = attribute.getAttributeJavaType(); - if ( !( attributeJavaType instanceof PrimitiveJavaType primitiveJavaType ) + if ( !( attribute.getAttributeJavaType() instanceof PrimitiveJavaType primitiveJavaType ) || primitiveJavaType.getPrimitiveClass() != javaType ) { throw new IllegalArgumentException( String.format( @@ -165,14 +165,15 @@ private void checkType(SingularPersistentAttribute attribute, Class jav } @Override - @SuppressWarnings("unchecked") public SqmSingularPersistentAttribute getDeclaredId(Class javaType) { ensureNoIdClass(); if ( id == null ) { throw new IllegalArgumentException( "The id attribute is not declared on this type [" + getTypeName() + "]" ); } checkType( id, javaType ); - return (SqmSingularPersistentAttribute) id; + @SuppressWarnings("unchecked") // safe, we just checked + final var castId = (SqmSingularPersistentAttribute) id; + return castId; } @Override @@ -226,14 +227,16 @@ else if ( idClassType instanceof SimpleDomainType simpleDomainType ) { } @Override - @SuppressWarnings("unchecked") public void visitIdClassAttributes(Consumer> attributeConsumer) { if ( nonAggregatedIdAttributes != null ) { nonAggregatedIdAttributes.forEach( attributeConsumer ); } - else if ( getSuperType() != null ) { - //noinspection rawtypes - getSuperType().visitIdClassAttributes( (Consumer) attributeConsumer ); + else { + final var superType = getSuperType(); + if ( superType != null ) { + //noinspection rawtypes, unchecked + superType.visitIdClassAttributes( (Consumer) attributeConsumer ); + } } } @@ -247,14 +250,15 @@ public boolean hasDeclaredVersionAttribute() { } @Override - @SuppressWarnings("unchecked") public SingularPersistentAttribute getVersion(Class javaType) { if ( hasVersionAttribute() ) { final var version = findVersionAttribute(); if ( version != null ) { checkType( version, javaType ); } - return (SingularPersistentAttribute) version; + @SuppressWarnings("unchecked") // safe, we just checked + final var castVersion = (SingularPersistentAttribute) version; + return castVersion; } else { return null; @@ -288,11 +292,12 @@ else if ( getSuperType() != null ) { } @Override - @SuppressWarnings("unchecked") public SingularPersistentAttribute getDeclaredVersion(Class javaType) { checkDeclaredVersion(); checkType( versionAttribute, javaType ); - return (SingularPersistentAttribute) versionAttribute; + @SuppressWarnings("unchecked") // safe, we just checked + final var castVersion = (SingularPersistentAttribute) versionAttribute; + return castVersion; } private void checkDeclaredVersion() { @@ -360,9 +365,8 @@ public void applyNonAggregatedIdAttributes( nonAggregatedIdAttributes.add( (SqmSingularPersistentAttribute) idAttribute ); if ( AbstractIdentifiableType.this == idAttribute.getDeclaringType() ) { @SuppressWarnings("unchecked") - // Safe, because we know it's declared by this type - final PersistentAttribute declaredAttribute = - (PersistentAttribute) idAttribute; + // Safe, because we know it's declared by this type + final var declaredAttribute = (PersistentAttribute) idAttribute; addAttribute( declaredAttribute ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainModelHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainModelHelper.java index d01d2ef09ac3..f4cfb2433533 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainModelHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainModelHelper.java @@ -5,7 +5,6 @@ package org.hibernate.metamodel.model.domain.internal; import org.hibernate.metamodel.MappingMetamodel; -import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.ManagedDomainType; @@ -28,9 +27,9 @@ static boolean isCompatible( return true; } else { - final ModelPart modelPart1 = + final var modelPart1 = getEntityAttributeModelPart( attribute1, attribute1.getDeclaringType(), mappingMetamodel ); - final ModelPart modelPart2 = + final var modelPart2 = getEntityAttributeModelPart( attribute2, attribute2.getDeclaringType(), mappingMetamodel ); return modelPart1 != null && modelPart2 != null @@ -43,13 +42,13 @@ static ModelPart getEntityAttributeModelPart( ManagedDomainType domainType, MappingMetamodel mappingMetamodel) { if ( domainType instanceof EntityDomainType ) { - final EntityMappingType entity = mappingMetamodel.getEntityDescriptor( domainType.getTypeName() ); - return entity.findSubPart( attribute.getName() ); + return mappingMetamodel.getEntityDescriptor( domainType.getTypeName() ) + .findSubPart( attribute.getName() ); } else { ModelPart candidate = null; - for ( ManagedDomainType subType : domainType.getSubTypes() ) { - final ModelPart modelPart = getEntityAttributeModelPart( attribute, subType, mappingMetamodel ); + for ( var subType : domainType.getSubTypes() ) { + final var modelPart = getEntityAttributeModelPart( attribute, subType, mappingMetamodel ); if ( modelPart != null ) { if ( candidate != null && !isCompatibleModelPart( candidate, modelPart ) ) { return null; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java index 267c7cba8051..223e6ee38cc1 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java @@ -5,9 +5,12 @@ package org.hibernate.metamodel.model.domain.internal; import java.io.Serializable; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import org.checkerframework.checker.nullness.qual.Nullable; +import org.hibernate.AssertionFailure; import org.hibernate.metamodel.UnsupportedMappingException; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; import org.hibernate.metamodel.model.domain.DomainType; @@ -33,6 +36,7 @@ public class EmbeddableTypeImpl implements SqmEmbeddableDomainType, Serializable { private final boolean isDynamic; private final EmbeddedDiscriminatorSqmPathSource discriminatorPathSource; + private final List> subtypes = new ArrayList<>(); public EmbeddableTypeImpl( JavaType javaType, @@ -61,15 +65,27 @@ public PersistenceType getPersistenceType() { public int getTupleLength() { int count = 0; for ( var attribute : getSingularAttributes() ) { - count += ( (SqmDomainType) attribute.getType() ).getTupleLength(); + if ( attribute.getType() instanceof SqmDomainType domainType ) { + count += domainType.getTupleLength(); + } + else { + throw new AssertionFailure( "Should have been a domain type" ); + } } return count; } @Override public Collection> getSubTypes() { - //noinspection unchecked - return (Collection>) super.getSubTypes(); + return subtypes; + } + + @Override + public void addSubType(ManagedDomainType subType) { + super.addSubType( subType ); + if ( subType instanceof SqmEmbeddableDomainType entityDomainType ) { + subtypes.add( entityDomainType ); + } } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java index b9f2da1a067a..0fa0b6261c57 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java @@ -7,7 +7,9 @@ import java.io.ObjectStreamException; import java.io.Serial; import java.io.Serializable; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Locale; import jakarta.persistence.metamodel.EntityType; @@ -15,19 +17,17 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.mapping.PersistentClass; import org.hibernate.metamodel.UnsupportedMappingException; -import org.hibernate.metamodel.mapping.DiscriminatorType; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityVersionMapping; import org.hibernate.metamodel.model.domain.IdentifiableDomainType; import org.hibernate.metamodel.model.domain.JpaMetamodel; +import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.PersistentAttribute; import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; -import org.hibernate.persister.entity.EntityPersister; import org.hibernate.query.PathException; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.domain.SqmDomainType; -import org.hibernate.query.sqm.tree.domain.SqmManagedDomainType; import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPersistentAttribute; import org.hibernate.query.sqm.tree.domain.SqmEntityDomainType; @@ -35,6 +35,7 @@ import static jakarta.persistence.metamodel.Bindable.BindableType.ENTITY_TYPE; import static jakarta.persistence.metamodel.Type.PersistenceType.ENTITY; +import static jakarta.persistence.metamodel.Type.PersistenceType.MAPPED_SUPERCLASS; import static org.hibernate.metamodel.model.domain.internal.DomainModelHelper.isCompatible; /** @@ -50,6 +51,7 @@ public class EntityTypeImpl private final String jpaEntityName; private final JpaMetamodelImplementor metamodel; private final SqmPathSource discriminatorPathSource; + private final List> subtypes = new ArrayList<>(); public EntityTypeImpl( String entityName, @@ -77,10 +79,10 @@ public EntityTypeImpl( } private EntityDiscriminatorSqmPathSource entityDiscriminatorPathSource(JpaMetamodelImplementor metamodel) { - final EntityPersister entityDescriptor = + final var entityDescriptor = metamodel.getMappingMetamodel() .getEntityDescriptor( getHibernateEntityName() ); - final DiscriminatorType discriminatorType = entityDescriptor.getDiscriminatorDomainType(); + final var discriminatorType = entityDescriptor.getDiscriminatorDomainType(); return discriminatorType == null ? null : new EntityDiscriminatorSqmPathSource<>( discriminatorType, this, entityDescriptor ); } @@ -176,13 +178,19 @@ else if ( EntityDiscriminatorMapping.matchesRoleName( name ) ) { @Override public @Nullable SqmPathSource findSubPathSource(String name, boolean includeSubtypes) { - final PersistentAttribute attribute = super.findAttribute( name ); + final var attribute = super.findAttribute( name ); if ( attribute != null ) { + if ( attribute.getDeclaringType().getPersistenceType() == MAPPED_SUPERCLASS ) { + final var concreteGeneric = findConcreteGenericAttribute( name ); + if ( concreteGeneric != null ) { + return (SqmPathSource) concreteGeneric; + } + } return (SqmPathSource) attribute; } else { if ( includeSubtypes ) { - final PersistentAttribute subtypeAttribute = findSubtypeAttribute( name ); + final var subtypeAttribute = findSubtypeAttribute( name ); if ( subtypeAttribute != null ) { return (SqmPathSource) subtypeAttribute; } @@ -201,8 +209,8 @@ else if ( EntityDiscriminatorMapping.matchesRoleName( name ) ) { private SqmPersistentAttribute findSubtypeAttribute(String name) { SqmPersistentAttribute subtypeAttribute = null; - for ( SqmManagedDomainType subtype : getSubTypes() ) { - final SqmPersistentAttribute candidate = subtype.findSubTypesAttribute( name ); + for ( var subtype : super.getSubTypes() ) { + final var candidate = subtype.findSubTypesAttribute( name ); if ( candidate != null ) { if ( subtypeAttribute != null && !isCompatible( subtypeAttribute, candidate, metamodel.getMappingMetamodel() ) ) { @@ -249,8 +257,15 @@ public PersistenceType getPersistenceType() { @Override public Collection> getSubTypes() { - //noinspection unchecked - return (Collection>) super.getSubTypes(); + return subtypes; + } + + @Override + public void addSubType(ManagedDomainType subType) { + super.addSubType( subType ); + if ( subType instanceof SqmEntityDomainType entityDomainType ) { + subtypes.add( entityDomainType ); + } } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java index c0694990ba70..f0ffc1f23837 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java @@ -67,11 +67,11 @@ */ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable { - private static class ImportInfo { + private static class ImportInfo { private final String importedName; - private Class loadedClass; // could be null for boot metamodel import; not final to allow for populating later + private Class loadedClass; // could be null for boot metamodel import; not final to allow for populating later - private ImportInfo(String importedName, Class loadedClass) { + private ImportInfo(String importedName, Class loadedClass) { this.importedName = importedName; this.loadedClass = loadedClass; } @@ -94,7 +94,7 @@ private ImportInfo(String importedName, Class loadedClass) { private final Map, String> entityProxyInterfaceMap = new HashMap<>(); - private final Map> nameToImportMap = new ConcurrentHashMap<>(); + private final Map nameToImportMap = new ConcurrentHashMap<>(); private final Map knownInvalidnameToImportMap = new ConcurrentHashMap<>(); @@ -116,15 +116,14 @@ public ServiceRegistry getServiceRegistry() { return serviceRegistry; } - @Override @Deprecated - public @Nullable ManagedDomainType findManagedType(@Nullable String typeName) { - //noinspection unchecked - return typeName == null ? null : (ManagedDomainType) managedTypeByName.get( typeName ); + @Override + public @Nullable ManagedDomainType findManagedType(@Nullable String typeName) { + return typeName == null ? null : managedTypeByName.get( typeName ); } @Override - public ManagedDomainType managedType(String typeName) { - final ManagedDomainType managedType = findManagedType( typeName ); + public ManagedDomainType managedType(String typeName) { + final var managedType = findManagedType( typeName ); if ( managedType == null ) { throw new IllegalArgumentException( "Not a managed type: " + typeName ); } @@ -193,11 +192,10 @@ public EmbeddableDomainType embeddable(String embeddableName) { return embeddableType; } - @Override @Deprecated - public EntityDomainType getHqlEntityReference(String entityName) { - Class loadedClass = null; - //noinspection unchecked - final var importInfo = (ImportInfo) resolveImport( entityName ); + @Override + public EntityDomainType getHqlEntityReference(String entityName) { + Class loadedClass = null; + final var importInfo = resolveImport( entityName ); if ( importInfo != null ) { loadedClass = importInfo.loadedClass; entityName = importInfo.importedName; @@ -205,13 +203,11 @@ public EntityDomainType getHqlEntityReference(String entityName) { final var entityDescriptor = findEntityType( entityName ); if ( entityDescriptor != null ) { - //noinspection unchecked - return (EntityDomainType) entityDescriptor; + return entityDescriptor; } if ( loadedClass == null ) { - //noinspection unchecked - loadedClass = (Class) resolveRequestedClass( entityName ); + loadedClass = resolveRequestedClass( entityName ); // populate the class cache for boot metamodel imports if ( importInfo != null && loadedClass != null ) { importInfo.loadedClass = loadedClass; @@ -223,9 +219,9 @@ public EntityDomainType getHqlEntityReference(String entityName) { return null; } - @Override @Deprecated - public EntityDomainType resolveHqlEntityReference(String entityName) { - final EntityDomainType hqlEntityReference = getHqlEntityReference( entityName ); + @Override + public EntityDomainType resolveHqlEntityReference(String entityName) { + final var hqlEntityReference = getHqlEntityReference( entityName ); if ( hqlEntityReference == null ) { throw new EntityTypeException( "Could not resolve entity name '" + entityName + "'", entityName ); } @@ -444,11 +440,11 @@ public Map> getNamedEntityGraphs(Class e @Override public String qualifyImportableName(String queryName) { - final ImportInfo importInfo = resolveImport( queryName ); + final var importInfo = resolveImport( queryName ); return importInfo == null ? null : importInfo.importedName; } - private ImportInfo resolveImport(final String name) { + private ImportInfo resolveImport(final String name) { final var importInfo = nameToImportMap.get( name ); //optimal path first if ( importInfo != null ) { @@ -461,7 +457,7 @@ private ImportInfo resolveImport(final String name) { } else { // see if the name is a fully qualified class name - final Class loadedClass = resolveRequestedClass( name ); + final var loadedClass = resolveRequestedClass( name ); if ( loadedClass == null ) { // it is NOT a fully qualified class name - add a marker entry, so we do not keep trying later // note that ConcurrentHashMap does not support null value so a marker entry is needed @@ -481,7 +477,7 @@ private ImportInfo resolveImport(final String name) { else { // it is a fully qualified class name - add it to the cache // so to not needing to load from the classloader again - final ImportInfo info = new ImportInfo<>( name, loadedClass ); + final var info = new ImportInfo( name, loadedClass ); nameToImportMap.put( name, info ); return info; } @@ -609,7 +605,7 @@ public void processJpa( RuntimeModelCreationContext runtimeModelCreationContext) { bootMetamodel.getImports() .forEach( (key, value) -> nameToImportMap.put( key, - new ImportInfo<>( value, null ) ) ); + new ImportInfo( value, null ) ) ); this.entityProxyInterfaceMap.putAll( entityProxyInterfaceMap ); final var context = new MetadataContext( diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java index eb6030e662f8..13549780a83f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java @@ -103,7 +103,7 @@ else if ( "id".equalsIgnoreCase( name ) ) { @Override public @Nullable SqmPathSource getIdentifierDescriptor() { - return (SqmPathSource) super.getIdentifierDescriptor(); + return super.getIdentifierDescriptor(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java index a5c20d424709..30887186f042 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java @@ -418,13 +418,13 @@ public Set> getEmbeddables() { return jpaMetamodel.getEmbeddables(); } - @Override @Deprecated - public @Nullable ManagedDomainType findManagedType(@Nullable String typeName) { + @Override + public @Nullable ManagedDomainType findManagedType(@Nullable String typeName) { return jpaMetamodel.findManagedType( typeName ); } - @Override @Deprecated - public ManagedDomainType managedType(String typeName) { + @Override + public ManagedDomainType managedType(String typeName) { return jpaMetamodel.managedType( typeName ); } @@ -448,13 +448,13 @@ public EmbeddableDomainType embeddable(String embeddableName) { return jpaMetamodel.embeddable( embeddableName ); } - @Override @Deprecated - public EntityDomainType getHqlEntityReference(String entityName) { + @Override + public EntityDomainType getHqlEntityReference(String entityName) { return jpaMetamodel.getHqlEntityReference( entityName ); } - @Override @Deprecated - public EntityDomainType resolveHqlEntityReference(String entityName) { + @Override + public EntityDomainType resolveHqlEntityReference(String entityName) { return jpaMetamodel.resolveHqlEntityReference( entityName ); } @@ -650,13 +650,13 @@ public String[] getAllCollectionRoles() { return basicType; } - final ManagedDomainType managedType = jpaMetamodel.findManagedType( javaType ); + final var managedType = jpaMetamodel.findManagedType( javaType ); if ( managedType != null ) { return (BindableType) managedType; } final var javaTypeRegistry = typeConfiguration.getJavaTypeRegistry(); - final JavaType javaTypeDescriptor = javaTypeRegistry.findDescriptor( javaType ); + final var javaTypeDescriptor = javaTypeRegistry.findDescriptor( javaType ); if ( javaTypeDescriptor != null ) { final JdbcType recommendedJdbcType = javaTypeDescriptor.getRecommendedJdbcType( typeConfiguration.getCurrentBaseSqlTypeIndicators() ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java index 0d1ad4d88b6b..265c9ea46e8e 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java @@ -5,7 +5,6 @@ package org.hibernate.query.hql.internal; import org.hibernate.metamodel.model.domain.JpaMetamodel; -import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.query.SemanticException; import org.hibernate.query.hql.spi.DotIdentifierConsumer; import org.hibernate.query.hql.spi.SemanticPathPart; @@ -16,6 +15,7 @@ import org.hibernate.query.sqm.function.SqmFunctionDescriptor; import org.hibernate.query.sqm.spi.SqmCreationContext; import org.hibernate.query.sqm.tree.domain.SqmPath; +import org.hibernate.query.sqm.tree.domain.SqmTreatedPath; import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral; import org.hibernate.query.sqm.tree.expression.SqmExpression; import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral; @@ -92,16 +92,18 @@ public void consumeIdentifier(String identifier, boolean isBase, boolean isTermi @Override public void consumeTreat(String importableName, boolean isTerminal) { - final SqmPath sqmPath = (SqmPath) currentPart; - currentPart = sqmPath.treatAs( treatTarget( importableName ) ); + currentPart = treat( importableName, (SqmPath) currentPart ); } - private Class treatTarget(String typeName) { - final ManagedDomainType managedType = + private SqmTreatedPath treat(String importableName, SqmPath path) { + return path.treatAs( treatTarget( path, importableName ) ); + } + + private Class treatTarget(SqmPath path, String typeName) { + final var javaType = creationState.getCreationContext().getJpaMetamodel() - // TODO: don't use this unsafe, deprecated method - .managedType( typeName ); - return managedType.getJavaType(); + .managedType( typeName ).getJavaType(); + return javaType.asSubclass( path.getJavaType() ); } protected void reset() { @@ -214,7 +216,7 @@ private SemanticPathPart resolveLiteralType(JpaMetamodel jpaMetamodel, NodeBuild return null; } else { - final ManagedDomainType managedType = jpaMetamodel.managedType( importableName ); + final var managedType = jpaMetamodel.managedType( importableName ); if ( managedType instanceof SqmEntityDomainType entityDomainType ) { return new SqmLiteralEntityType<>( entityDomainType, nodeBuilder ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/QualifiedJoinPathConsumer.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/QualifiedJoinPathConsumer.java index 5f013adb41dc..280f48f4445a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/QualifiedJoinPathConsumer.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/QualifiedJoinPathConsumer.java @@ -4,8 +4,6 @@ */ package org.hibernate.query.hql.internal; -import org.hibernate.metamodel.model.domain.EntityDomainType; -import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.query.PathException; import org.hibernate.query.SemanticException; import org.hibernate.query.hql.spi.DotIdentifierConsumer; @@ -17,9 +15,9 @@ import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.spi.SqmCreationHelper; import org.hibernate.query.sqm.tree.SqmJoinType; -import org.hibernate.query.sqm.tree.cte.SqmCteStatement; import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor; +import org.hibernate.query.sqm.tree.domain.SqmTreatedFrom; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmCteJoin; import org.hibernate.query.sqm.tree.from.SqmEntityJoin; @@ -27,6 +25,7 @@ import org.hibernate.query.sqm.tree.from.SqmJoin; import org.hibernate.query.sqm.tree.from.SqmRoot; +import org.hibernate.query.sqm.tree.from.SqmTreatedAttributeJoin; import org.jboss.logging.Logger; import static org.hibernate.query.sqm.internal.SqmUtil.findCompatibleFetchJoin; @@ -240,7 +239,7 @@ else if ( fetch ) { boolean allowReuse, SqmCreationState creationState, SqmJoinable joinSource) { - final SqmJoin join = joinSource.createSqmJoin( + final var join = joinSource.createSqmJoin( lhs, joinType, isTerminal ? alias : allowReuse ? SqmCreationHelper.IMPLICIT_ALIAS : null, @@ -296,24 +295,39 @@ public void consumeIdentifier(String identifier, boolean isTerminal, boolean all @Override public void consumeTreat(String typeName, boolean isTerminal) { + currentPath = treat( typeName, isTerminal ); + creationState.getCurrentProcessingState().getPathRegistry().register( currentPath ); + } + + private SqmTreatedFrom treat(String typeName, boolean isTerminal) { if ( isTerminal ) { - currentPath = fetch - ? ( (SqmAttributeJoin) currentPath ).treatAs( treatTarget( typeName ), alias, true ) - : currentPath.treatAs( treatTarget( typeName ), alias ); + return fetch + ? treatTerminalFetch( currentPath, typeName ) + : treatTerminal( currentPath, typeName ); } else { - currentPath = currentPath.treatAs( treatTarget( typeName ) ); + return treatNonTerminal( currentPath, typeName ); } - creationState.getCurrentProcessingState().getPathRegistry().register( currentPath ); } - private Class treatTarget(String typeName) { - final ManagedDomainType managedType = - creationState.getCreationContext() - .getJpaMetamodel() - // TODO: don't use this unsafe, deprecated method - .managedType( typeName ); - return managedType.getJavaType(); + private SqmTreatedFrom treatNonTerminal(SqmFrom path, String typeName) { + return path.treatAs( treatTarget( path, typeName ) ); + } + + private SqmTreatedAttributeJoin treatTerminalFetch(SqmFrom path, String typeName) { + final var attributeJoin = (SqmAttributeJoin) path; + return attributeJoin.treatAs( treatTarget( path, typeName ), alias, true ); + } + + private SqmTreatedFrom treatTerminal(SqmFrom path, String typeName) { + return path.treatAs( treatTarget( path, typeName ), alias ); + } + + private Class treatTarget(SqmPath path, String typeName) { + final var javaType = + creationState.getCreationContext().getJpaMetamodel() + .managedType( typeName ).getJavaType(); + return javaType.asSubclass( path.getJavaType() ); } @Override @@ -359,11 +373,11 @@ public void consumeIdentifier(String identifier, boolean isTerminal, boolean all path.append( identifier ); if ( isTerminal ) { final String fullPath = path.toString(); - final EntityDomainType joinedEntityType = + final var joinedEntityType = creationState.getCreationContext().getJpaMetamodel() .getHqlEntityReference( fullPath ); if ( joinedEntityType == null ) { - final SqmCteStatement cteStatement = creationState.findCteStatement( fullPath ); + final var cteStatement = creationState.findCteStatement( fullPath ); if ( cteStatement != null ) { //noinspection rawtypes,unchecked join = new SqmCteJoin( cteStatement, alias, joinType, sqmRoot ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java index 7dfe199268ee..33044d94cabd 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java @@ -2138,8 +2138,7 @@ public final SqmCrossJoin visitCrossJoin(HqlParser.CrossJoinContext ctx) { protected void consumeCrossJoin(HqlParser.CrossJoinContext parserJoin, SqmRoot sqmRoot) { final String name = getEntityName( parserJoin.entityName() ); - final EntityDomainType entityDescriptor = - getJpaMetamodel().resolveHqlEntityReference( name ); + final var entityDescriptor = getJpaMetamodel().resolveHqlEntityReference( name ); if ( entityDescriptor instanceof SqmPolymorphicRootDescriptor ) { throw new SemanticException( "Unmapped polymorphic reference cannot be used as a target of 'cross join'", diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmPathSource.java index b6634190173f..8416108acfa8 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmPathSource.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmPathSource.java @@ -88,7 +88,7 @@ default SqmPathSource getSubPathSource(String name) { * @throws IllegalArgumentException if the subPathSource is not found */ default SqmPathSource getSubPathSource(String name, boolean subtypes) { - final SqmPathSource subPathSource = findSubPathSource( name, subtypes ); + final var subPathSource = findSubPathSource( name, subtypes ); if ( subPathSource == null ) { throw new PathElementException( String.format( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java index 46c3af8fb73f..0bcb51539151 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java @@ -402,7 +402,7 @@ private static boolean isMappedSuperclassTypeAssignable( EntityType rhsType, BindingContext bindingContext) { - for ( ManagedDomainType candidate : lhsType.getSubTypes() ) { + for ( var candidate : lhsType.getSubTypes() ) { if ( candidate instanceof EntityType candidateEntityType && isEntityTypeAssignable( candidateEntityType, rhsType, bindingContext ) ) { return true; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java index 116f068bf3dc..7328d783ee8e 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java @@ -11,7 +11,6 @@ import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.model.domain.JpaMetamodel; -import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.ast.SqlAstJoinType; import org.hibernate.sql.ast.tree.expression.Expression; @@ -198,9 +197,8 @@ public EmbeddableInitializer createInitializer(InitializerParent parent, A public boolean appliesTo(GraphImplementor graphImplementor, JpaMetamodel metamodel) { // We use managedType here since this fetch could correspond // to an entity type if the embeddable is an @IdClass - final ManagedDomainType managedType = - metamodel.managedType( getResultJavaType().getTypeName() ); - return GraphHelper.appliesTo( graphImplementor, managedType ); + return GraphHelper.appliesTo( graphImplementor, + metamodel.managedType( getResultJavaType().getTypeName() ) ); } @Override diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/MockSessionFactory.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/MockSessionFactory.java index caf404ff29d3..8325307d04fe 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/MockSessionFactory.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/MockSessionFactory.java @@ -860,14 +860,14 @@ else if (isEntityDefined(queryName)) { } @Override - public @Nullable ManagedDomainType findManagedType(@Nullable String typeName) { + public @Nullable ManagedDomainType findManagedType(@Nullable String typeName) { // TODO: not every ManagedDomainType is an EntityDomainType! return typeName == null ? null : new MockEntityDomainType<>(new MockJavaType<>(typeName)); } @Override public ManagedDomainType findManagedType(Class cls) { - return findManagedType( cls.getName() ); + return cls == null ? null : new MockEntityDomainType<>(new MockJavaType<>(cls.getName())); } @Override