diff --git a/hibernate-core/src/main/java/org/hibernate/binder/internal/AttributeAccessorBinder.java b/hibernate-core/src/main/java/org/hibernate/binder/internal/AttributeAccessorBinder.java index 2bb6738ea4dc..e7461384e280 100644 --- a/hibernate-core/src/main/java/org/hibernate/binder/internal/AttributeAccessorBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/binder/internal/AttributeAccessorBinder.java @@ -24,8 +24,8 @@ public void bind( MetadataBuildingContext buildingContext, PersistentClass persistentClass, Property property) { - String value = accessor.value(); - Class type = accessor.strategy(); + final String value = accessor.value(); + final Class type = accessor.strategy(); if ( !value.isEmpty() ) { property.setPropertyAccessorName( value ); } diff --git a/hibernate-core/src/main/java/org/hibernate/binder/internal/CollateBinder.java b/hibernate-core/src/main/java/org/hibernate/binder/internal/CollateBinder.java index 5d973926ed91..18e6255a878e 100644 --- a/hibernate-core/src/main/java/org/hibernate/binder/internal/CollateBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/binder/internal/CollateBinder.java @@ -23,7 +23,7 @@ public class CollateBinder implements AttributeBinder { @Override public void bind(Collate collate, MetadataBuildingContext context, PersistentClass entity, Property property) { - Value value = property.getValue(); + final Value value = property.getValue(); if ( value instanceof OneToMany ) { throw new AnnotationException( "One to many association '" + property.getName() + "' was annotated '@Collate'"); diff --git a/hibernate-core/src/main/java/org/hibernate/binder/internal/CommentBinder.java b/hibernate-core/src/main/java/org/hibernate/binder/internal/CommentBinder.java index ddc2371f71fd..a9ec86aa4015 100644 --- a/hibernate-core/src/main/java/org/hibernate/binder/internal/CommentBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/binder/internal/CommentBinder.java @@ -27,9 +27,9 @@ public class CommentBinder implements AttributeBinder, TypeBinder { @Override public void bind(Comment comment, MetadataBuildingContext context, PersistentClass entity, Property property) { - String text = comment.value(); - String on = comment.on(); - Value value = property.getValue(); + final String text = comment.value(); + final String on = comment.on(); + final Value value = property.getValue(); if ( value instanceof OneToMany ) { throw new AnnotationException( "One to many association '" + property.getName() + "' was annotated '@Comment'"); @@ -64,9 +64,9 @@ else if ( value instanceof Collection collection ) { @Override public void bind(Comment comment, MetadataBuildingContext context, PersistentClass entity) { - String text = comment.value(); - String on = comment.on(); - Table primary = entity.getTable(); + final String text = comment.value(); + final String on = comment.on(); + final Table primary = entity.getTable(); // by default, the comment goes on the primary table if ( on.isEmpty() || primary.getName().equalsIgnoreCase( on ) ) { primary.setComment( text ); @@ -74,7 +74,7 @@ public void bind(Comment comment, MetadataBuildingContext context, PersistentCla else { // but if 'on' is explicit, it can go on a secondary table for ( Join join : entity.getJoins() ) { - Table secondary = join.getTable(); + final Table secondary = join.getTable(); if ( secondary.getName().equalsIgnoreCase( on ) ) { secondary.setComment( text ); return; diff --git a/hibernate-core/src/main/java/org/hibernate/binder/internal/CommentsBinder.java b/hibernate-core/src/main/java/org/hibernate/binder/internal/CommentsBinder.java index e930b91c90fd..54aaa8335a17 100644 --- a/hibernate-core/src/main/java/org/hibernate/binder/internal/CommentsBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/binder/internal/CommentsBinder.java @@ -5,7 +5,6 @@ package org.hibernate.binder.internal; import org.hibernate.AnnotationException; -import org.hibernate.annotations.Comment; import org.hibernate.annotations.Comments; import org.hibernate.binder.AttributeBinder; import org.hibernate.binder.TypeBinder; @@ -25,9 +24,9 @@ public class CommentsBinder implements TypeBinder, AttributeBinder { @Override public void bind(Comments comments, MetadataBuildingContext context, PersistentClass entity, Property property) { - final CommentBinder commentBinder = new CommentBinder(); + final var commentBinder = new CommentBinder(); final Set ons = new HashSet<>( comments.value().length ); - for ( Comment comment : comments.value() ) { + for ( var comment : comments.value() ) { if ( !ons.add( comment.on() ) ) { throw new AnnotationException( "Multiple '@Comment' annotations of '" + property.getName() + "' had the same 'on'" ); @@ -38,9 +37,9 @@ public void bind(Comments comments, MetadataBuildingContext context, PersistentC @Override public void bind(Comments comments, MetadataBuildingContext context, PersistentClass entity) { - final CommentBinder commentBinder = new CommentBinder(); + final var commentBinder = new CommentBinder(); final Set ons = new HashSet<>( comments.value().length ); - for ( Comment comment : comments.value() ) { + for ( var comment : comments.value() ) { if ( !ons.add( comment.on() ) ) { throw new AnnotationException( "Multiple '@Comment' annotations of entity '" + entity.getEntityName() + "' had the same 'on'" ); diff --git a/hibernate-core/src/main/java/org/hibernate/binder/internal/TenantIdBinder.java b/hibernate-core/src/main/java/org/hibernate/binder/internal/TenantIdBinder.java index d9ef91b90825..df9562ef9944 100644 --- a/hibernate-core/src/main/java/org/hibernate/binder/internal/TenantIdBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/binder/internal/TenantIdBinder.java @@ -10,16 +10,13 @@ import org.hibernate.MappingException; import org.hibernate.annotations.TenantId; import org.hibernate.binder.AttributeBinder; -import org.hibernate.boot.spi.InFlightMetadataCollector; import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.mapping.Column; import org.hibernate.mapping.Formula; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; -import org.hibernate.mapping.Selectable; import org.hibernate.metamodel.mapping.JdbcMapping; -import org.hibernate.type.BasicType; import org.hibernate.type.descriptor.java.JavaType; import static java.util.Collections.emptyMap; @@ -41,14 +38,14 @@ public void bind( MetadataBuildingContext buildingContext, PersistentClass persistentClass, Property property) { - final InFlightMetadataCollector collector = buildingContext.getMetadataCollector(); + final var collector = buildingContext.getMetadataCollector(); final String returnedClassName = property.getReturnedClassName(); - final BasicType tenantIdType = + final var tenantIdType = collector.getTypeConfiguration().getBasicTypeRegistry() .getRegisteredType( returnedClassName ); - final FilterDefinition filterDefinition = collector.getFilterDefinition( FILTER_NAME ); + final var filterDefinition = collector.getFilterDefinition( FILTER_NAME ); if ( filterDefinition == null ) { collector.addFilterDefinition( new FilterDefinition( @@ -93,7 +90,7 @@ private String columnNameOrFormula(Property property) { if ( property.getColumnSpan() != 1 ) { throw new MappingException( "@TenantId attribute must be mapped to a single column or formula" ); } - final Selectable selectable = property.getSelectables().get( 0 ); + final var selectable = property.getSelectables().get( 0 ); if ( selectable instanceof Formula formula ) { return formula.getFormula(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/LoadQueryInfluencers.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/LoadQueryInfluencers.java index e2c197a30434..cd495ccde8c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/LoadQueryInfluencers.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/LoadQueryInfluencers.java @@ -74,8 +74,8 @@ public LoadQueryInfluencers(SessionFactoryImplementor sessionFactory, SessionCre batchSize = options.getDefaultBatchFetchSize(); subselectFetchEnabled = options.isSubselectFetchEnabled(); effectiveEntityGraph = new EffectiveEntityGraph(); - for ( FilterDefinition filterDefinition : sessionFactory.getAutoEnabledFilters() ) { - final FilterImpl filter = new FilterImpl( filterDefinition ); + for ( var filterDefinition : sessionFactory.getAutoEnabledFilters() ) { + final var filter = new FilterImpl( filterDefinition ); if ( enabledFilters == null ) { enabledFilters = new TreeMap<>(); } @@ -84,7 +84,7 @@ public LoadQueryInfluencers(SessionFactoryImplementor sessionFactory, SessionCre } public EffectiveEntityGraph applyEntityGraph(@Nullable RootGraphImplementor rootGraph, @Nullable GraphSemantic graphSemantic) { - final EffectiveEntityGraph effectiveEntityGraph = getEffectiveEntityGraph(); + final var effectiveEntityGraph = getEffectiveEntityGraph(); if ( graphSemantic != null ) { if ( rootGraph == null ) { throw new IllegalArgumentException( "Graph semantic specified, but no RootGraph was supplied" ); @@ -141,13 +141,13 @@ public boolean hasEnabledFilters() { } public Map getEnabledFilters() { - final TreeMap enabledFilters = this.enabledFilters; + final var enabledFilters = this.enabledFilters; if ( enabledFilters == null ) { return emptyMap(); } else { // First, validate all the enabled filters... - for ( Filter filter : enabledFilters.values() ) { + for ( var filter : enabledFilters.values() ) { //TODO: this implementation has bad performance filter.validate(); } @@ -187,7 +187,7 @@ public Object getFilterParameterValue(String filterParameterName) { if ( enabledFilters == null ) { throw new IllegalArgumentException( "Filter [" + parsed[0] + "] currently not enabled" ); } - final FilterImpl filter = (FilterImpl) enabledFilters.get( parsed[0] ); + final var filter = (FilterImpl) enabledFilters.get( parsed[0] ); if ( filter == null ) { throw new IllegalArgumentException( "Filter [" + parsed[0] + "] currently not enabled" ); } @@ -195,7 +195,7 @@ public Object getFilterParameterValue(String filterParameterName) { } public static String [] parseFilterParameterName(String filterParameterName) { - int dot = filterParameterName.lastIndexOf( '.' ); + final int dot = filterParameterName.lastIndexOf( '.' ); if ( dot <= 0 ) { throw new IllegalArgumentException( "Invalid filter-parameter name format [" + filterParameterName + "]; expecting {filter-name}.{param-name}" @@ -246,14 +246,10 @@ public void disableFetchProfile(String name) throws UnknownProfileException { @Internal public @Nullable HashSet adjustFetchProfiles( @Nullable Set disabledFetchProfiles, @Nullable Set enabledFetchProfiles) { - final HashSet currentEnabledFetchProfileNames = this.enabledFetchProfileNames; - final HashSet oldFetchProfiles; - if ( currentEnabledFetchProfileNames == null || currentEnabledFetchProfileNames.isEmpty() ) { - oldFetchProfiles = null; - } - else { - oldFetchProfiles = new HashSet<>( currentEnabledFetchProfileNames ); - } + final var oldFetchProfiles = + enabledFetchProfileNames != null && !enabledFetchProfileNames.isEmpty() + ? new HashSet<>( enabledFetchProfileNames ) + : null; if ( disabledFetchProfiles != null && enabledFetchProfileNames != null ) { enabledFetchProfileNames.removeAll( disabledFetchProfiles ); } @@ -292,7 +288,7 @@ public void setBatchSize(int batchSize) { } public int effectiveBatchSize(CollectionPersister persister) { - int persisterBatchSize = persister.getBatchSize(); + final int persisterBatchSize = persister.getBatchSize(); // persister-specific batch size overrides global setting // (note that due to legacy, -1 means no explicit setting) return persisterBatchSize >= 0 ? persisterBatchSize : batchSize; @@ -303,7 +299,7 @@ public boolean effectivelyBatchLoadable(CollectionPersister persister) { } public int effectiveBatchSize(EntityPersister persister) { - int persisterBatchSize = persister.getBatchSize(); + final int persisterBatchSize = persister.getBatchSize(); // persister-specific batch size overrides global setting // (note that due to legacy, -1 means no explicit setting) return persisterBatchSize >= 0 ? persisterBatchSize : batchSize; @@ -331,7 +327,8 @@ private boolean isSubselectFetchEnabledInProfile(CollectionPersister persister) if ( hasEnabledFetchProfiles() ) { for ( String profile : getEnabledFetchProfileNames() ) { final FetchProfile fetchProfile = - persister.getFactory().getSqlTranslationEngine().getFetchProfile( profile ) ; + persister.getFactory().getSqlTranslationEngine() + .getFetchProfile( profile ) ; if ( fetchProfile != null ) { final Fetch fetch = fetchProfile.getFetchByRole( persister.getRole() ); if ( fetch != null && fetch.getMethod() == SUBSELECT) { diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index a239edceea41..df4b50679741 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -11,6 +11,7 @@ import java.io.Serial; import java.sql.Connection; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -93,7 +94,6 @@ import org.hibernate.metamodel.spi.RuntimeMetamodelsImplementor; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.proxy.EntityNotFoundDelegate; -import org.hibernate.proxy.LazyInitializer; import org.hibernate.query.internal.QueryEngineImpl; import org.hibernate.query.named.NamedObjectRepository; import org.hibernate.query.spi.QueryEngine; @@ -192,7 +192,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { private final transient CurrentSessionContext currentSessionContext; private final transient Map filters; - private final transient java.util.Collection autoEnabledFilters = new HashSet<>(); + private final transient Collection autoEnabledFilters = new ArrayList<>(); private final transient JavaType tenantIdentifierJavaType; private final transient EventListenerGroups eventListenerGroups; @@ -251,19 +251,11 @@ public SessionFactoryImpl( filters = new HashMap<>( bootMetamodel.getFilterDefinitions() ); - final var tenantFilter = filters.get( TenantIdBinder.FILTER_NAME ); - if ( tenantFilter == null ) { - tenantIdentifierJavaType = options.getDefaultTenantIdentifierJavaType(); - } - else { - final var jdbcMapping = tenantFilter.getParameterJdbcMapping( TenantIdBinder.PARAMETER_NAME ); - assert jdbcMapping != null; - //noinspection unchecked - tenantIdentifierJavaType = jdbcMapping.getJavaTypeDescriptor(); - } - for ( var filterEntry : filters.entrySet() ) { - if ( filterEntry.getValue().isAutoEnabled() ) { - autoEnabledFilters.add( filterEntry.getValue() ); + tenantIdentifierJavaType = tenantIdentifierType( options ); + + for ( var filter : filters.values() ) { + if ( filter.isAutoEnabled() ) { + autoEnabledFilters.add( filter ); } } @@ -357,6 +349,19 @@ public SessionFactoryImpl( } } + private JavaType tenantIdentifierType(SessionFactoryOptions options) { + final var tenantFilter = filters.get( TenantIdBinder.FILTER_NAME ); + if ( tenantFilter == null ) { + return options.getDefaultTenantIdentifierJavaType(); + } + else { + final var jdbcMapping = tenantFilter.getParameterJdbcMapping( TenantIdBinder.PARAMETER_NAME ); + assert jdbcMapping != null; + //noinspection unchecked + return jdbcMapping.getJavaTypeDescriptor(); + } + } + private EventMonitor loadEventMonitor() { final var eventMonitors = classLoaderService.loadJavaServices( EventMonitor.class ); return eventMonitors.isEmpty() ? new EmptyEventMonitor() : eventMonitors.iterator().next(); @@ -642,27 +647,25 @@ public Session createEntityManager() { return buildEntityManager( SYNCHRONIZED, null ); } - private Session buildEntityManager(final SynchronizationType synchronizationType, final Map map) { + private Session buildEntityManager(SynchronizationType synchronizationType, Map map) { assert status != Status.CLOSED; - SessionBuilderImplementor builder = withOptions(); + var builder = withOptions(); builder.autoJoinTransactions( synchronizationType == SYNCHRONIZED ); if ( map != null ) { - //noinspection SuspiciousMethodCalls final Object tenantIdHint = map.get( HINT_TENANT_ID ); if ( tenantIdHint != null ) { - builder = (SessionBuilderImplementor) builder.tenantIdentifier( tenantIdHint ); + builder = builder.tenantIdentifier( tenantIdHint ); } } - final Session session = builder.openSession(); + final var session = builder.openSession(); if ( map != null ) { - for ( Map.Entry o : map.entrySet() ) { - final K key = o.getKey(); - if ( key instanceof String string ) { + for ( var entry : map.entrySet() ) { + if ( entry.getKey() instanceof String string ) { if ( !HINT_TENANT_ID.equals( string ) ) { - session.setProperty( string, o.getValue() ); + session.setProperty( string, entry.getValue() ); } } } @@ -670,8 +673,7 @@ private Session buildEntityManager(final SynchronizationType synchronizati return session; } - @Override @SuppressWarnings("unchecked") - public Session createEntityManager(Map map) { + public Session createEntityManager(Map map) { validateNotClosed(); return buildEntityManager( SYNCHRONIZED, map ); } @@ -695,8 +697,8 @@ private void errorIfResourceLocalDueToExplicitSynchronizationType() { } } - @Override @SuppressWarnings("unchecked") - public Session createEntityManager(SynchronizationType synchronizationType, Map map) { + @Override + public Session createEntityManager(SynchronizationType synchronizationType, Map map) { validateNotClosed(); errorIfResourceLocalDueToExplicitSynchronizationType(); return buildEntityManager( synchronizationType, map ); @@ -737,7 +739,7 @@ public RootGraphImplementor findEntityGraphByName(String name) { @Override public String bestGuessEntityName(Object object) { - final LazyInitializer initializer = extractLazyInitializer( object ); + final var initializer = extractLazyInitializer( object ); if ( initializer != null ) { // it is possible for this method to be called during flush processing, // so make certain that we do not accidentally initialize an uninitialized proxy @@ -803,8 +805,8 @@ public void close() { LOG.closingFactory( getUuid() ); observer.sessionFactoryClosing( this ); - // NOTE : the null checks below handle cases where close is called from - // a failed attempt to create the SessionFactory + // NOTE: the null checks below handle cases where close is called + // from a failed attempt to create the SessionFactory if ( cacheAccess != null ) { cacheAccess.close(); @@ -962,7 +964,7 @@ public FilterDefinition getFilterDefinition(String filterName) { } @Override - public java.util.Collection getAutoEnabledFilters() { + public Collection getAutoEnabledFilters() { return autoEnabledFilters; } @@ -1072,10 +1074,10 @@ public static Interceptor configuredInterceptor(Interceptor interceptor, Session } public static Interceptor configuredInterceptor(Interceptor interceptor, boolean explicitNoInterceptor, SessionFactoryOptions options) { - // NOTE : DO NOT return EmptyInterceptor.INSTANCE from here as a "default for the Session" - // we "filter" that one out here. The return from here should represent the - // explicitly configured Interceptor (if one). Return null from here instead; Session - // will handle it + // NOTE: DO NOT return EmptyInterceptor.INSTANCE from here as a "default for the Session" + // we "filter" that one out here. The return from here should represent the + // explicitly configured Interceptor (if one). Return null from here instead; + // Session will handle it if ( interceptor != null && interceptor != EmptyInterceptor.INSTANCE ) { return interceptor; @@ -1087,7 +1089,7 @@ public static Interceptor configuredInterceptor(Interceptor interceptor, boolean return optionsInterceptor; } - // If explicitly asking for no interceptor and there is no SessionFactory-scoped interceptors, then + // If explicitly asking for no interceptor and there is no SessionFactory-scoped interceptor, then // no need to inherit from the configured stateless session ones. if ( explicitNoInterceptor ) { return null; @@ -1349,7 +1351,7 @@ public SessionBuilderImpl eventListeners(SessionEventListener... listeners) { public SessionBuilderImpl clearEventListeners() { if ( listeners == null ) { //Needs to initialize explicitly to an empty list as otherwise "null" implies the default listeners will be applied - this.listeners = new ArrayList<>( 3 ); + listeners = new ArrayList<>( 3 ); } else { listeners.clear(); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java index f1dea4a5e78d..2a7e50bb2805 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java @@ -4,6 +4,8 @@ */ package org.hibernate.internal.util.collections; +import org.checkerframework.checker.nullness.qual.Nullable; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -258,27 +260,27 @@ public static Set makeCopy(Set source) { } } - public static boolean isEmpty(Collection collection) { + public static boolean isEmpty(@Nullable Collection collection) { return collection == null || collection.isEmpty(); } - public static boolean isEmpty(Map map) { + public static boolean isEmpty(@Nullable Map map) { return map == null || map.isEmpty(); } - public static boolean isNotEmpty(Collection collection) { + public static boolean isNotEmpty(@Nullable Collection collection) { return !isEmpty( collection ); } - public static boolean isNotEmpty(Map map) { + public static boolean isNotEmpty(@Nullable Map map) { return !isEmpty( map ); } - public static boolean isEmpty(Object[] objects) { + public static boolean isEmpty(@Nullable Object[] objects) { return objects == null || objects.length == 0; } - public static boolean isNotEmpty(Object[] objects) { + public static boolean isNotEmpty(@Nullable Object[] objects) { return objects != null && objects.length > 0; } @@ -309,7 +311,7 @@ public static Properties asProperties(Map map) { return properties; } else { - final Properties properties = new Properties(); + final var properties = new Properties(); if ( isNotEmpty( map ) ) { properties.putAll( map ); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/BaseNaturalIdLoadAccessImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/BaseNaturalIdLoadAccessImpl.java index c62a5d31060a..b5d76d4f4687 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/BaseNaturalIdLoadAccessImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/BaseNaturalIdLoadAccessImpl.java @@ -16,10 +16,6 @@ import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.UnknownProfileException; -import org.hibernate.engine.spi.EffectiveEntityGraph; -import org.hibernate.engine.spi.EntityEntry; -import org.hibernate.engine.spi.LoadQueryInfluencers; -import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.Status; import org.hibernate.graph.GraphSemantic; @@ -28,7 +24,6 @@ import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.proxy.HibernateProxy; -import org.hibernate.proxy.LazyInitializer; import static org.hibernate.engine.spi.NaturalIdResolutions.INVALID_NATURAL_ID_REFERENCE; import static org.hibernate.internal.NaturalIdHelper.performAnyNeededCrossReferenceSynchronizations; @@ -176,12 +171,10 @@ protected final T doLoad(Object normalizedNaturalIdValue) { return null; } else { - final SessionImplementor session = context.getSession(); - final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers(); - final var fetchProfiles = - influencers.adjustFetchProfiles( disabledFetchProfiles, enabledFetchProfiles ); - final EffectiveEntityGraph effectiveEntityGraph = - session.getLoadQueryInfluencers().applyEntityGraph( rootGraph, graphSemantic); + final var session = context.getSession(); + final var influencers = session.getLoadQueryInfluencers(); + final var fetchProfiles = influencers.adjustFetchProfiles( disabledFetchProfiles, enabledFetchProfiles ); + final var effectiveEntityGraph = influencers.applyEntityGraph( rootGraph, graphSemantic ); try { @SuppressWarnings("unchecked") final T loaded = cachedResolution != null @@ -189,9 +182,9 @@ protected final T doLoad(Object normalizedNaturalIdValue) { : (T) entityPersister().getNaturalIdLoader() .load( normalizedNaturalIdValue, this, session ); if ( loaded != null ) { - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); - final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( loaded ); - final EntityEntry entry = lazyInitializer != null + final var persistenceContext = session.getPersistenceContextInternal(); + final var lazyInitializer = HibernateProxy.extractLazyInitializer( loaded ); + final var entry = lazyInitializer != null ? persistenceContext.getEntry( lazyInitializer.getImplementation() ) : persistenceContext.getEntry( loaded ); assert entry != null; diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/CacheLoadHelper.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/CacheLoadHelper.java index 07826389124b..40dd844df471 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/CacheLoadHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/CacheLoadHelper.java @@ -8,8 +8,6 @@ import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor; -import org.hibernate.cache.spi.access.CollectionDataAccess; -import org.hibernate.cache.spi.access.EntityDataAccess; import org.hibernate.cache.spi.entry.CacheEntry; import org.hibernate.cache.spi.entry.CollectionCacheEntry; import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl; @@ -17,19 +15,12 @@ import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.engine.internal.TwoPhaseLoad; import org.hibernate.engine.spi.EntityEntry; -import org.hibernate.engine.spi.EntityHolder; import org.hibernate.engine.spi.EntityKey; -import org.hibernate.engine.spi.PersistenceContext; -import org.hibernate.engine.spi.PersistentAttributeInterceptor; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.Status; import org.hibernate.event.spi.LoadEventListener; -import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.proxy.LazyInitializer; -import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.type.Type; import org.hibernate.type.TypeHelper; @@ -77,32 +68,46 @@ private CacheLoadHelper() { * * @throws HibernateException Generally indicates problems applying a lock mode. */ - public static PersistenceContextEntry loadFromSessionCache(EntityKey keyToLoad, LockOptions lockOptions, LoadEventListener.LoadType options, SharedSessionContractImplementor session) { + public static PersistenceContextEntry loadFromSessionCache( + EntityKey keyToLoad, + LockOptions lockOptions, + LoadEventListener.LoadType options, + SharedSessionContractImplementor session) { final Object old = session.getEntityUsingInterceptor( keyToLoad ); - PersistenceContextEntry.EntityStatus entityStatus = MANAGED; + final PersistenceContextEntry.EntityStatus entityStatus; if ( old != null ) { // this object was already loaded - final EntityEntry oldEntry = session.getPersistenceContext().getEntry( old ); + final var oldEntry = session.getPersistenceContext().getEntry( old ); entityStatus = entityStatus( keyToLoad, options, session, oldEntry, old ); if ( entityStatus == MANAGED ) { upgradeLock( old, oldEntry, lockOptions, session ); } } + else { + entityStatus = MANAGED; + } return new PersistenceContextEntry( old, entityStatus ); } // Used by Hibernate Reactive - public static PersistenceContextEntry.EntityStatus entityStatus(EntityKey keyToLoad, LoadEventListener.LoadType options, SharedSessionContractImplementor session, EntityEntry oldEntry, Object old) { + public static PersistenceContextEntry.EntityStatus entityStatus( + EntityKey keyToLoad, + LoadEventListener.LoadType options, + SharedSessionContractImplementor session, + EntityEntry oldEntry, + Object old) { if ( options.isCheckDeleted() && oldEntry.getStatus().isDeletedOrGone() ) { LOADING_LOGGER.foundEntityScheduledForRemoval(); return REMOVED_ENTITY_MARKER; } - if ( options.isAllowNulls() && !session.getFactory().getMappingMetamodel() + else if ( options.isAllowNulls() && !session.getFactory().getMappingMetamodel() .getEntityDescriptor( keyToLoad.getEntityName() ).isInstance( old ) ) { LOADING_LOGGER.foundEntityWrongType(); return INCONSISTENT_RTN_CLASS_MARKER; } - return MANAGED; + else { + return MANAGED; + } } /** @@ -127,9 +132,8 @@ public static Object loadFromSecondLevelCache( && source.getCacheMode().isGetEnabled() && lockMode.lessThan( LockMode.READ ); if ( useCache ) { - final Object ce = getFromSharedCache( entityKey.getIdentifier(), persister, source ); - // nothing was found in cache - return ce == null ? null : processCachedEntry( entity, persister, ce, source, entityKey ); + final Object cacheEntry = getFromSharedCache( entityKey.getIdentifier(), persister, source ); + return cacheEntry == null ? null : processCachedEntry( entity, persister, cacheEntry, source, entityKey ); } else { // we can't use cache here @@ -140,38 +144,33 @@ public static Object loadFromSecondLevelCache( private static Object getFromSharedCache( final Object entityId, final EntityPersister persister, - SharedSessionContractImplementor source) { - final EntityDataAccess cache = persister.getCacheAccessStrategy(); - final SessionFactoryImplementor factory = source.getFactory(); - final Object cacheKey = cache.generateCacheKey( - entityId, - persister, - factory, - source.getTenantIdentifier() - ); - final Object ce = fromSharedCache( source, cacheKey, persister, persister.getCacheAccessStrategy() ); - final StatisticsImplementor statistics = factory.getStatistics(); + final SharedSessionContractImplementor source) { + final var cache = persister.getCacheAccessStrategy(); + final var factory = source.getFactory(); + final Object cacheKey = cache.generateCacheKey( entityId, persister, factory, source.getTenantIdentifier() ); + final Object cacheEntry = fromSharedCache( source, cacheKey, persister, persister.getCacheAccessStrategy() ); + final var statistics = factory.getStatistics(); if ( statistics.isStatisticsEnabled() ) { - final NavigableRole rootEntityRole = getRootEntityRole( persister ); + final var rootEntityRole = getRootEntityRole( persister ); final String regionName = cache.getRegion().getName(); - if ( ce == null ) { + if ( cacheEntry == null ) { statistics.entityCacheMiss( rootEntityRole, regionName ); } else { statistics.entityCacheHit( rootEntityRole, regionName ); } } - return ce; + return cacheEntry; } private static Object processCachedEntry( final Object instanceToLoad, final EntityPersister persister, - final Object ce, + final Object cacheEntry, final SharedSessionContractImplementor source, final EntityKey entityKey) { - final CacheEntry entry = (CacheEntry) - persister.getCacheEntryStructure().destructure( ce, source.getFactory() ); + final var entry = (CacheEntry) + persister.getCacheEntryStructure().destructure( cacheEntry, source.getFactory() ); if ( entry.isReferenceEntry() ) { if ( instanceToLoad != null ) { throw new HibernateException( "Attempt to load entity from cache using provided object instance, " @@ -192,8 +191,8 @@ private static Object processCachedEntry( entityKey ); if ( !persister.isInstance( entity ) ) { - // Cleanup the inconsistent return class entity from the persistence context - final PersistenceContext persistenceContext = source.getPersistenceContext(); + // Clean up the inconsistent return class entity from the persistence context + final var persistenceContext = source.getPersistenceContext(); persistenceContext.removeEntry( entity ); persistenceContext.removeEntity( entityKey ); return null; @@ -222,12 +221,10 @@ private static void makeEntityCircularReferenceSafe( Object entity, EntityKey entityKey) { // make it circular-reference safe - final PersistenceContext persistenceContext = session.getPersistenceContext(); + final var persistenceContext = session.getPersistenceContext(); if ( isManagedEntity( entity ) ) { - final EntityHolder entityHolder = - persistenceContext.addEntityHolder( entityKey, entity ); - final EntityEntry entityEntry = - persistenceContext.addReferenceEntry( entity, Status.READ_ONLY ); + final var entityHolder = persistenceContext.addEntityHolder( entityKey, entity ); + final var entityEntry = persistenceContext.addReferenceEntry( entity, Status.READ_ONLY ); entityHolder.setEntityEntry( entityEntry ); } else { @@ -251,30 +248,26 @@ private static Object convertCacheEntryToEntity( Object instanceToLoad, EntityKey entityKey) { - final EntityPersister subclassPersister = + final var subclassPersister = source.getFactory().getMappingMetamodel() .getEntityDescriptor( entry.getSubclass() ); - final PersistenceContext persistenceContext = source.getPersistenceContextInternal(); - final EntityHolder oldHolder = persistenceContext.getEntityHolder( entityKey ); + final var persistenceContext = source.getPersistenceContextInternal(); + final var oldHolder = persistenceContext.getEntityHolder( entityKey ); final Object entity; if ( instanceToLoad != null ) { entity = instanceToLoad; } else { - if ( oldHolder != null && oldHolder.getEntity() != null ) { - // Use the entity which might already be - entity = oldHolder.getEntity(); - } - else { - entity = source.instantiate( subclassPersister, entityId ); - } + entity = oldHolder != null && oldHolder.getEntity() != null + ? oldHolder.getEntity() + : source.instantiate( subclassPersister, entityId ); } if ( isPersistentAttributeInterceptable( entity ) ) { - PersistentAttributeInterceptor persistentAttributeInterceptor = + final var persistentAttributeInterceptor = asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor(); - // if we do this after the entity has been initialized the + // if we do this after the entity has been initialized, the // BytecodeLazyAttributeInterceptor#isAttributeLoaded(String fieldName) // would return false if ( persistentAttributeInterceptor == null @@ -285,13 +278,13 @@ private static Object convertCacheEntryToEntity( } // make it circular-reference safe - final EntityHolder holder = persistenceContext.addEntityHolder( entityKey, entity ); + final var holder = persistenceContext.addEntityHolder( entityKey, entity ); final Object proxy = holder.getProxy(); final boolean isReadOnly; if ( proxy != null ) { // there is already a proxy for this impl // only set the status to read-only if the proxy is read-only - final LazyInitializer lazyInitializer = extractLazyInitializer( proxy ); + final var lazyInitializer = extractLazyInitializer( proxy ); assert lazyInitializer != null; lazyInitializer.setImplementation( entity ); isReadOnly = lazyInitializer.isReadOnly(); @@ -316,7 +309,7 @@ private static Object convertCacheEntryToEntity( final Type[] types = subclassPersister.getPropertyTypes(); // initializes the entity by (desired) side effect - final StandardCacheEntryImpl standardCacheEntry = (StandardCacheEntryImpl) entry; + final var standardCacheEntry = (StandardCacheEntryImpl) entry; final Object[] values = standardCacheEntry.assemble( entity, entityId, @@ -334,7 +327,7 @@ private static Object convertCacheEntryToEntity( ); } final Object version = getVersion( values, subclassPersister ); - final EntityEntry entityEntry = persistenceContext.addEntry( + final var entityEntry = persistenceContext.addEntry( entity, isReadOnly ? Status.READ_ONLY : Status.MANAGED, values, @@ -346,9 +339,7 @@ private static Object convertCacheEntryToEntity( subclassPersister, false ); - holder.setEntityEntry( - entityEntry - ); + holder.setEntityEntry( entityEntry ); subclassPersister.afterInitialize( entity, source ); entityEntry.postLoad( entity ); persistenceContext.initializeNonLazyCollections(); @@ -372,43 +363,58 @@ public static boolean initializeCollectionFromCache( CollectionPersister persister, PersistentCollection collection, SharedSessionContractImplementor source) { - if ( persister.hasCache() && source.getCacheMode().isGetEnabled() ) { - final SessionFactoryImplementor factory = source.getFactory(); - final CollectionDataAccess cacheAccessStrategy = persister.getCacheAccessStrategy(); - final Object ck = cacheAccessStrategy.generateCacheKey( key, persister, factory, source.getTenantIdentifier() ); - final Object ce = fromSharedCache( source, ck, persister, cacheAccessStrategy ); - - final StatisticsImplementor statistics = factory.getStatistics(); - if ( statistics.isStatisticsEnabled() ) { - final NavigableRole navigableRole = persister.getNavigableRole(); - final String regionName = cacheAccessStrategy.getRegion().getName(); - if ( ce == null ) { - statistics.collectionCacheMiss( navigableRole, regionName ); - } - else { - statistics.collectionCacheHit( navigableRole, regionName ); - } - } - - if ( ce == null ) { + final Object cachedEntry = getFromSharedCache( key, persister, source ); + if ( cachedEntry == null ) { return false; } else { - final CollectionCacheEntry cacheEntry = (CollectionCacheEntry) - persister.getCacheEntryStructure().destructure( ce, factory ); - final PersistenceContext persistenceContext = source.getPersistenceContextInternal(); - cacheEntry.assemble( collection, persister, persistenceContext.getCollectionOwner( key, persister ) ); - persistenceContext.getCollectionEntry( collection ).postInitialize( collection, source ); - // addInitializedCollection(collection, persister, key); + processCachedEntry( key, persister, cachedEntry, collection, source ); return true; } } else { + // we can't use cache here return false; } } + private static void processCachedEntry( + Object key, + CollectionPersister persister, + Object cachedEntry, + PersistentCollection collection, + SharedSessionContractImplementor source) { + final var cacheEntry = (CollectionCacheEntry) + persister.getCacheEntryStructure().destructure( cachedEntry, source.getFactory() ); + final var persistenceContext = source.getPersistenceContextInternal(); + cacheEntry.assemble( collection, persister, persistenceContext.getCollectionOwner( key, persister ) ); + persistenceContext.getCollectionEntry( collection ).postInitialize( collection, source ); + // addInitializedCollection(collection, persister, key); + } + + private static Object getFromSharedCache( + Object key, + CollectionPersister persister, + SharedSessionContractImplementor source) { + final var factory = source.getFactory(); + final var cache = persister.getCacheAccessStrategy(); + final Object cacheKey = cache.generateCacheKey( key, persister, factory, source.getTenantIdentifier() ); + final Object cachedEntry = fromSharedCache( source, cacheKey, persister, cache ); + final var statistics = factory.getStatistics(); + if ( statistics.isStatisticsEnabled() ) { + final var navigableRole = persister.getNavigableRole(); + final String regionName = cache.getRegion().getName(); + if ( cachedEntry == null ) { + statistics.collectionCacheMiss( navigableRole, regionName ); + } + else { + statistics.collectionCacheHit( navigableRole, regionName ); + } + } + return cachedEntry; + } + public record PersistenceContextEntry(Object entity, EntityStatus status) { public enum EntityStatus { MANAGED, 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 e2b059274526..980912f266fc 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 @@ -19,19 +19,13 @@ import org.hibernate.LockOptions; import org.hibernate.ObjectNotFoundException; import org.hibernate.UnknownProfileException; -import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor; import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor; -import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata; -import org.hibernate.engine.spi.EffectiveEntityGraph; -import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.event.spi.LoadEventListener; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.spi.RootGraphImplementor; -import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.proxy.LazyInitializer; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.spi.TypeConfiguration; @@ -111,8 +105,8 @@ public final T getReference(Object id) { // Hibernate Reactive overrides this protected T perform(Supplier executor) { - final SessionImplementor session = context.getSession(); - final CacheMode sessionCacheMode = session.getCacheMode(); + final var session = context.getSession(); + final var sessionCacheMode = session.getCacheMode(); boolean cacheModeChanged = false; if ( cacheMode != null ) { @@ -125,11 +119,9 @@ protected T perform(Supplier executor) { } try { - final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers(); - final HashSet fetchProfiles = - influencers.adjustFetchProfiles( disabledFetchProfiles, enabledFetchProfiles ); - final EffectiveEntityGraph effectiveEntityGraph = - influencers.applyEntityGraph( rootGraph, graphSemantic); + final var influencers = session.getLoadQueryInfluencers(); + final var fetchProfiles = influencers.adjustFetchProfiles( disabledFetchProfiles, enabledFetchProfiles ); + final var effectiveEntityGraph = influencers.applyEntityGraph( rootGraph, graphSemantic); try { return executor.get(); } @@ -149,8 +141,8 @@ protected T perform(Supplier executor) { @SuppressWarnings( "unchecked" ) // Hibernate Reactive overrides this protected T doGetReference(Object id) { - final SessionImplementor session = context.getSession(); - final EntityMappingType concreteType = entityPersister.resolveConcreteProxyTypeForId( id, session ); + final var session = context.getSession(); + final var concreteType = entityPersister.resolveConcreteProxyTypeForId( id, session ); return (T) context.load( LoadEventListener.LOAD, coerceId( id, session.getFactory() ), concreteType.getEntityName(), lockOptions, isReadOnly( session ) ); } @@ -175,7 +167,7 @@ public Optional loadOptional(Object id) { @SuppressWarnings( "unchecked" ) // Hibernate Reactive overrides this protected T doLoad(Object id) { - final SessionImplementor session = context.getSession(); + final var session = context.getSession(); Object result; try { result = context.load( LoadEventListener.GET, coerceId( id, session.getFactory() ), @@ -209,21 +201,19 @@ protected Object coerceId(Object id, SessionFactoryImplementor factory) { private void initializeIfNecessary(Object result) { if ( result != null ) { - final LazyInitializer lazyInitializer = extractLazyInitializer( result ); + final var lazyInitializer = extractLazyInitializer( result ); if ( lazyInitializer != null ) { if ( lazyInitializer.isUninitialized() ) { lazyInitializer.initialize(); } } else { - final BytecodeEnhancementMetadata enhancementMetadata = + final var enhancementMetadata = entityPersister.getEntityMetamodel().getBytecodeEnhancementMetadata(); - if ( enhancementMetadata.isEnhancedForLazyLoading() ) { - final BytecodeLazyAttributeInterceptor interceptor = - enhancementMetadata.extractLazyInterceptor( result); - if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor lazinessInterceptor ) { - lazinessInterceptor.forceInitialize( result, null ); - } + if ( enhancementMetadata.isEnhancedForLazyLoading() + && enhancementMetadata.extractLazyInterceptor( result ) + instanceof EnhancementAsProxyLazinessInterceptor lazinessInterceptor ) { + lazinessInterceptor.forceInitialize( result, null ); } } }