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/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/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/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..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) { @@ -2789,23 +2787,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 +2823,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 +2845,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/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/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/JpaMetamodel.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java index ca496516c904..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 @@ -34,7 +34,7 @@ public interface JpaMetamodel extends Metamodel { /** * Access to a managed type through its name */ - ManagedDomainType managedType(String typeName); + ManagedDomainType managedType(String typeName); /** * Access to an entity supporting Hibernate's entity-name feature @@ -50,13 +50,13 @@ public interface JpaMetamodel extends Metamodel { * Specialized handling for resolving entity-name references in * an HQL query */ - EntityDomainType getHqlEntityReference(String entityName); + EntityDomainType getHqlEntityReference(String entityName); /** * Specialized handling for resolving entity-name references in * an HQL query */ - EntityDomainType resolveHqlEntityReference(String entityName); + EntityDomainType resolveHqlEntityReference(String entityName); /** * Same as {@link #managedType(Class)} except {@code null} is returned rather @@ -80,7 +80,7 @@ public interface JpaMetamodel extends Metamodel { * Same as {@link #managedType(String)} except {@code null} is returned rather * than throwing an exception */ - @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 e412aa39bb02..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 @@ -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; @@ -66,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; } @@ -93,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,14 +117,13 @@ public ServiceRegistry getServiceRegistry() { } @Override - public @Nullable ManagedDomainType findManagedType(@Nullable String typeName) { - //noinspection unchecked - return typeName == null ? null : (ManagedDomainType) managedTypeByName.get( typeName ); + 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 ); } @@ -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 ); } @@ -193,23 +193,22 @@ public EmbeddableDomainType embeddable(String embeddableName) { } @Override - public EntityDomainType getHqlEntityReference(String entityName) { - Class loadedClass = null; - final ImportInfo importInfo = resolveImport( entityName ); + public EntityDomainType getHqlEntityReference(String entityName) { + Class loadedClass = null; + final var 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; + return entityDescriptor; } if ( loadedClass == null ) { loadedClass = resolveRequestedClass( entityName ); - // populate class cache for boot metamodel imports + // populate the class cache for boot metamodel imports if ( importInfo != null && loadedClass != null ) { importInfo.loadedClass = loadedClass; } @@ -221,24 +220,35 @@ public EntityDomainType getHqlEntityReference(String entityName) { } @Override - public EntityDomainType resolveHqlEntityReference(String entityName) { - final EntityDomainType hqlEntityReference = getHqlEntityReference( entityName ); + public EntityDomainType resolveHqlEntityReference(String entityName) { + final var hqlEntityReference = getHqlEntityReference( entityName ); if ( hqlEntityReference == null ) { throw new EntityTypeException( "Could not resolve entity name '" + entityName + "'", 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 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 +259,15 @@ public ManagedDomainType managedType(Class cls) { @Override @Nullable public EntityDomainType findEntityType(Class cls) { - final ManagedType type = managedTypeByClass.get( cls ); - if ( !( type instanceof EntityDomainType ) ) { - return null; - } - //noinspection unchecked - return (EntityDomainType) type; + return checkDomainType( cls, managedTypeByClass.get( cls ) ) + instanceof EntityDomainType entityDomainType + ? entityDomainType + : 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 +276,15 @@ public EntityDomainType entity(Class cls) { @Override public @Nullable EmbeddableDomainType findEmbeddableType(Class cls) { - final ManagedType type = managedTypeByClass.get( cls ); - if ( !( type instanceof EmbeddableDomainType ) ) { - return null; - } - //noinspection unchecked - return (EmbeddableDomainType) type; + return checkDomainType( cls, managedTypeByClass.get( cls ) ) + instanceof EmbeddableDomainType embeddableDomainType + ? embeddableDomainType + : 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 +328,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 +389,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 +402,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 +421,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() ); } @@ -434,16 +440,15 @@ 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) { - 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 +456,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 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 + // 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 +475,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 var info = new ImportInfo( name, loadedClass ); nameToImportMap.put( name, info ); return info; } @@ -481,24 +486,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 +512,7 @@ private void applyNamedEntityGraphs(Collection named } - private Class resolveRequestedClass(String entityName) { + private Class resolveRequestedClass(String entityName) { try { return classLoaderService.classForName( entityName ); } @@ -522,7 +525,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 +541,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 +604,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 +629,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 +732,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; @@ -746,23 +748,26 @@ 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) { - 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 +778,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 +791,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 +807,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 +828,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/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 33209e400641..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 @@ -419,12 +419,12 @@ public Set> getEmbeddables() { } @Override - public @Nullable ManagedDomainType findManagedType(@Nullable String typeName) { + public @Nullable ManagedDomainType findManagedType(@Nullable String typeName) { return jpaMetamodel.findManagedType( typeName ); } @Override - public ManagedDomainType managedType(String typeName) { + public ManagedDomainType managedType(String typeName) { return jpaMetamodel.managedType( typeName ); } @@ -449,12 +449,12 @@ public EmbeddableDomainType embeddable(String embeddableName) { } @Override - public EntityDomainType getHqlEntityReference(String entityName) { + public EntityDomainType getHqlEntityReference(String entityName) { return jpaMetamodel.getHqlEntityReference( entityName ); } @Override - public EntityDomainType resolveHqlEntityReference(String entityName) { + 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 1cd1d5d0e2ac..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,15 +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() - .managedType( typeName ); - return managedType.getJavaType(); + .managedType( typeName ).getJavaType(); + return javaType.asSubclass( path.getJavaType() ); } protected void reset() { @@ -213,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 7f2e838a6067..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,22 +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() - .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 @@ -357,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 2e721a911f52..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,6 @@ 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 ); if ( entityDescriptor instanceof SqmPolymorphicRootDescriptor ) { @@ -2579,8 +2577,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/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/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/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/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/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..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 @@ -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,15 +135,17 @@ 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() ); + final ArrayList> newTreats = + new ArrayList<>( treats.size() ); for ( SqmTreatedFrom treat : treats ) { newTreats.add( treat.copy( context ) ); } @@ -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/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/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/graph/embeddable/internal/EmbeddableFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java index 23445bb15838..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 @@ -195,8 +195,10 @@ 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 + return GraphHelper.appliesTo( graphImplementor, + metamodel.managedType( getResultJavaType().getTypeName() ) ); } @Override 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..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 @@ -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 @@ -131,36 +133,34 @@ public boolean hasCollectionInitializers() { } @Override - @AllowReflection public T readRow(RowProcessingState rowProcessingState) { - coordinateInitializers( rowProcessingState ); + coordinateInitializers(); + final T result = getResult( rowProcessingState ); + finishUpRow(); + return result; + } - final T result; + @AllowReflection + @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/type/AbstractStandardBasicType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java index d41f3de19ffc..4dca9e44c747 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; @@ -55,18 +54,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 @@ -94,7 +93,7 @@ public T fromString(CharSequence string) { } protected MutabilityPlan getMutabilityPlan() { - return this.mutabilityPlan; + return mutabilityPlan; } @Override @@ -174,7 +173,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 +184,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 +206,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 +221,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 +242,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,23 +267,17 @@ public final boolean isMutable() { } @Override - @SuppressWarnings("unchecked") - public final Object deepCopy(Object value, SessionFactoryImplementor factory) { - return deepCopy( (T) 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 - @SuppressWarnings("unchecked") - public final Serializable disassemble(Object value, SharedSessionContractImplementor session, Object owner) throws HibernateException { - return getMutabilityPlan().disassemble( (T) 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 ); } @@ -296,16 +286,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 +302,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 +316,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 +330,8 @@ public void nullSafeSet( Object value, int index, boolean[] settable, - SharedSessionContractImplementor session) throws SQLException { + SharedSessionContractImplementor session) + throws SQLException { } @@ -356,9 +340,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 +362,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/BasicArrayType.java b/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java index 963bb7b436c2..13502e29806b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/BasicArrayType.java @@ -6,34 +6,47 @@ 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; +import static java.lang.Character.toUpperCase; + /** * A type that maps between {@link java.sql.Types#ARRAY ARRAY} and {@code T[]} * * @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 = + 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) { 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; }; } @@ -59,20 +72,50 @@ 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 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 ( arrayTypeDescriptor == null ) { + // for hibernate-vector + return super.isEqual( one, another ); + } + else 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 == null + ? super.deepCopy( value, factory ) // for hibernate-vector + : arrayTypeDescriptor.deepCopy( value ); + } } 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/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 d7d1207db2bd..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 @@ -19,7 +19,8 @@ import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; 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 @@ -97,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 ); @@ -106,7 +107,7 @@ BasicType createTypeUsingConverter( elementType, arrayJdbcType( typeConfiguration, elementType, columnTypeInformation, indicators ), this, - new ArrayConverter<>( valueConverter, this, relationalJavaType ) + new ArrayConverter<>( valueConverter, this, relationalJavaType, elementType ) ); } @@ -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/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..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 @@ -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; } } @@ -256,24 +262,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 ); @@ -296,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]; @@ -361,33 +383,52 @@ 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 ) ); } } + // 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 @@ -396,16 +437,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/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/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..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 @@ -96,28 +96,26 @@ 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 - @SuppressWarnings("unchecked") public T wrap(X value, WrapperOptions options) { if ( value == null ) { return null; @@ -141,7 +139,7 @@ else if ( value instanceof Number number ) { return fromLong( number.longValue() ); } else { - return (T) value; + return cast( value ); } } 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..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 @@ -75,37 +75,36 @@ 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 ) { return true; } - 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 ) { + else if ( one == null || another == null) { 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; + } } } @@ -127,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() ); } 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 ); 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; 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", 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