Fix Delaying Basic attribute fetching

This commit is contained in:
Andrea Boriero 2021-09-30 19:31:01 +02:00 committed by Christian Beikov
parent b872d8ad74
commit 18fee9cf5a
5 changed files with 72 additions and 6 deletions

View File

@ -83,6 +83,7 @@ public class ResultMementoEntityJpa implements ResultMementoEntity, FetchMemento
)
);
final boolean isEnhancedForLazyLoading = entityDescriptor.getRepresentationStrategy().isBytecodeEnhanced();
// Implicit basic fetches are DELAYED by default, so register fetch builders for the remaining basic fetchables
entityDescriptor.visitAttributeMappings(
attributeMapping -> {
@ -90,7 +91,8 @@ public class ResultMementoEntityJpa implements ResultMementoEntity, FetchMemento
if ( attributeMapping instanceof BasicValuedModelPart ) {
fetchBuilderCreator = k -> new DelayedFetchBuilderBasicPart(
navigablePath.append( k ),
(BasicValuedModelPart) attributeMapping
(BasicValuedModelPart) attributeMapping,
isEnhancedForLazyLoading
);
explicitFetchBuilderMap.computeIfAbsent(
attributeMapping.getFetchableName(),

View File

@ -25,12 +25,15 @@ public class DelayedFetchBuilderBasicPart
implements CompleteFetchBuilder, BasicValuedFetchBuilder, ModelPartReferenceBasic {
private final NavigablePath navigablePath;
private final BasicValuedModelPart referencedModelPart;
private final boolean isEnhancedForLazyLoading;
public DelayedFetchBuilderBasicPart(
NavigablePath navigablePath,
BasicValuedModelPart referencedModelPart) {
BasicValuedModelPart referencedModelPart,
boolean isEnhancedForLazyLoading) {
this.navigablePath = navigablePath;
this.referencedModelPart = referencedModelPart;
this.isEnhancedForLazyLoading = isEnhancedForLazyLoading;
}
@Override
@ -58,6 +61,7 @@ public class DelayedFetchBuilderBasicPart
true,
null,
FetchTiming.DELAYED,
isEnhancedForLazyLoading,
domainResultCreationState
);
}

View File

@ -0,0 +1,30 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql.results.graph;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
public class UnfetchedBasicPartResultAssembler<J> implements DomainResultAssembler<J> {
private final JavaTypeDescriptor<J> javaTypeDescriptor;
public UnfetchedBasicPartResultAssembler(JavaTypeDescriptor<J> javaTypeDescriptor) {
this.javaTypeDescriptor = javaTypeDescriptor;
}
@Override
public J assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
return null;
}
@Override
public JavaTypeDescriptor<J> getAssembledJavaTypeDescriptor() {
return javaTypeDescriptor;
}
}

View File

@ -12,6 +12,7 @@ import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.UnfetchedBasicPartResultAssembler;
import org.hibernate.sql.results.graph.UnfetchedResultAssembler;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultAssembler;
@ -44,18 +45,45 @@ public class BasicFetch<T> implements Fetch, BasicResultGraphNode<T> {
BasicValueConverter<T, ?> valueConverter,
FetchTiming fetchTiming,
DomainResultCreationState creationState) {
this(
valuesArrayPosition,
fetchParent,
fetchablePath,
valuedMapping,
nullable,
valueConverter,
fetchTiming,
true,
creationState
);
}
public BasicFetch(
int valuesArrayPosition,
FetchParent fetchParent,
NavigablePath fetchablePath,
BasicValuedModelPart valuedMapping,
boolean nullable,
BasicValueConverter<T, ?> valueConverter,
FetchTiming fetchTiming,
boolean canBasicPartFetchBeDelayed,
DomainResultCreationState creationState) {
this.nullable = nullable;
this.navigablePath = fetchablePath;
this.fetchParent = fetchParent;
this.valuedMapping = valuedMapping;
this.fetchTiming = fetchTiming;
@SuppressWarnings("unchecked")
final JavaTypeDescriptor<T> javaTypeDescriptor = (JavaTypeDescriptor<T>) valuedMapping.getJavaTypeDescriptor();
@SuppressWarnings("unchecked") final JavaTypeDescriptor<T> javaTypeDescriptor = (JavaTypeDescriptor<T>) valuedMapping.getJavaTypeDescriptor();
// lazy basic attribute
if ( fetchTiming == FetchTiming.DELAYED && valuesArrayPosition == -1 ) {
if ( canBasicPartFetchBeDelayed ) {
this.assembler = new UnfetchedResultAssembler<>( javaTypeDescriptor );
}
else {
this.assembler = new UnfetchedBasicPartResultAssembler( javaTypeDescriptor );
}
}
else {
this.assembler = new BasicResultAssembler<>(
valuesArrayPosition,

View File

@ -20,6 +20,7 @@ import org.junit.jupiter.api.Test;
import static org.hibernate.testing.orm.junit.ExtraAssertions.assertTyping;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
/**
* @author Steve Ebersole
@ -86,7 +87,8 @@ public class ResultMappingTest extends BaseSessionFactoryFunctionalTest {
final ResultSetOutput resultSetReturn = assertTyping( ResultSetOutput.class, currentOutput );
final Object result = resultSetReturn.getSingleResult();
assertTyping( H2ProcTesting.MyEntity.class, result );
assertEquals( "Steve", ( (H2ProcTesting.MyEntity) result ).name );
assertNull( ( (H2ProcTesting.MyEntity) result ).name );
assertNotNull( ( (H2ProcTesting.MyEntity) result ).id );
}
);
}