diff --git a/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java b/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java index fcf0a955e7..82ff20e1a1 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java @@ -1788,4 +1788,8 @@ public interface CoreMessageLogger extends BasicLogger { @Message(value = "Multi-table insert is not available due to missing identity and window function support for: %s", id = 509) void multiTableInsertNotAvailable(String entityName); + @LogMessage(level = WARN) + @Message(value = "Association with `fetch=\"join\"`/`@Fetch(FetchMode.JOIN)` and `lazy=\"true\"`/`FetchType.LAZY` found. This will be interpreted as lazy: %s", id = 510) + void fetchModeJoinWithLazyWarning(String role); + } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/FetchOptionsHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/FetchOptionsHelper.java index f057fd7dd2..421a37ada5 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/FetchOptionsHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/FetchOptionsHelper.java @@ -10,6 +10,8 @@ import org.hibernate.FetchMode; import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchTiming; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; import org.hibernate.persister.collection.AbstractCollectionPersister; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; @@ -20,6 +22,9 @@ import org.hibernate.type.AssociationType; * @author Steve Ebersole */ public final class FetchOptionsHelper { + + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( FetchOptionsHelper.class ); + private FetchOptionsHelper() { } @@ -90,10 +95,15 @@ public final class FetchOptionsHelper { FetchStyle style, AssociationType type, boolean lazy, + String role, SessionFactoryImplementor sessionFactory) { switch ( style ) { case JOIN: { - return lazy ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE; + if ( lazy ) { + LOG.fetchModeJoinWithLazyWarning( role ); + return FetchTiming.DELAYED; + } + return FetchTiming.IMMEDIATE; } case BATCH: case SUBSELECT: diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java index 7c42e91526..9f38e747dc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java @@ -754,6 +754,7 @@ public class MappingModelCreationHelper { style, collectionDescriptor.getCollectionType(), collectionDescriptor.isLazy(), + collectionDescriptor.getRole(), sessionFactory ); @@ -1579,17 +1580,17 @@ public class MappingModelCreationHelper { ); final FetchTiming fetchTiming; - + final String role = declaringType.getNavigableRole().toString() + "." + bootProperty.getName(); final boolean lazy = value.isLazy(); if ( lazy && entityPersister.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) { if ( value.isUnwrapProxy() ) { - fetchTiming = FetchOptionsHelper.determineFetchTiming( fetchStyle, type, lazy, sessionFactory ); + fetchTiming = FetchOptionsHelper.determineFetchTiming( fetchStyle, type, lazy, role, sessionFactory ); } else if ( value instanceof ManyToOne && value.isNullable() && ( (ManyToOne) value ).isIgnoreNotFound() ) { fetchTiming = FetchTiming.IMMEDIATE; } else { - fetchTiming = FetchOptionsHelper.determineFetchTiming( fetchStyle, type, lazy, sessionFactory ); + fetchTiming = FetchOptionsHelper.determineFetchTiming( fetchStyle, type, lazy, role, sessionFactory ); } } else if ( !lazy @@ -1598,7 +1599,7 @@ public class MappingModelCreationHelper { fetchTiming = FetchTiming.IMMEDIATE; } else { - fetchTiming = FetchOptionsHelper.determineFetchTiming( fetchStyle, type, lazy, sessionFactory ); + fetchTiming = FetchOptionsHelper.determineFetchTiming( fetchStyle, type, lazy, role, sessionFactory ); } final ToOneAttributeMapping attributeMapping = new ToOneAttributeMapping( diff --git a/migration-guide.adoc b/migration-guide.adoc index 5f6bab0629..5230e88150 100644 --- a/migration-guide.adoc +++ b/migration-guide.adoc @@ -560,6 +560,21 @@ The legacy Hibernate Criteria API which was deprecated back in Hibernate 5.x and Usually, all queries using the legacy API can be modeled with the JPA Criteria API. In some cases it is necessary to use the Hibernate JPA Criteria extensions. +=== HQL fetch all properties clause + +The `fetch all properties` clause was removed from the HQL language without a replacement. +A similar behavior can be achieved by constructing an entity graph and applying that as load graph: + +```java +EntityGraph entityGraph = entityManager.createEntityGraph( Document.class ); +for ( Attribute attr : entityManager.getMetamodel().entity( Document.class ).getAttributes() ) { + entityGraph.addAttributeNodes( attr.getName() ); +} +List documents = s.createQuery( "from Document", Document.class ) + .setHint( "jakarta.persistence.loadgraph", entityGraph ) + .getResultList(); +``` + === JMX integration Hibernate no longer provides built-in support for integrating itself with JMX environments.