HHH-18271 Improve fast path for row reading
This commit is contained in:
parent
e9513b1db5
commit
cf44c30bf2
|
@ -40,7 +40,7 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParametersList;
|
import org.hibernate.sql.exec.spi.JdbcParametersList;
|
||||||
import org.hibernate.sql.results.graph.DomainResult;
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||||
import org.hibernate.sql.results.internal.RowTransformerDatabaseSnapshotImpl;
|
import org.hibernate.sql.results.internal.RowTransformerArrayImpl;
|
||||||
import org.hibernate.sql.results.spi.ListResultsConsumer;
|
import org.hibernate.sql.results.spi.ListResultsConsumer;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
@ -176,7 +176,7 @@ class DatabaseSnapshotExecutor {
|
||||||
jdbcSelect,
|
jdbcSelect,
|
||||||
jdbcParameterBindings,
|
jdbcParameterBindings,
|
||||||
new BaseExecutionContext( session ),
|
new BaseExecutionContext( session ),
|
||||||
RowTransformerDatabaseSnapshotImpl.instance(),
|
RowTransformerArrayImpl.instance(),
|
||||||
null,
|
null,
|
||||||
ListResultsConsumer.UniqueSemantic.FILTER,
|
ListResultsConsumer.UniqueSemantic.FILTER,
|
||||||
1
|
1
|
||||||
|
|
|
@ -6,16 +6,13 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.loader.ast.internal;
|
package org.hibernate.loader.ast.internal;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
|
||||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParametersList;
|
import org.hibernate.sql.exec.spi.JdbcParametersList;
|
||||||
import org.hibernate.sql.results.internal.RowTransformerDatabaseSnapshotImpl;
|
import org.hibernate.sql.results.internal.RowTransformerArrayImpl;
|
||||||
import org.hibernate.sql.results.spi.RowTransformer;
|
import org.hibernate.sql.results.spi.RowTransformer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,7 +34,7 @@ public class SingleIdArrayLoadPlan extends SingleIdLoadPlan<Object[]> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RowTransformer<Object[]> getRowTransformer() {
|
protected RowTransformer<Object[]> getRowTransformer() {
|
||||||
return RowTransformerDatabaseSnapshotImpl.instance();
|
return RowTransformerArrayImpl.instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ public class LoadingCollectionEntryImpl implements LoadingCollectionEntry {
|
||||||
|
|
||||||
final boolean hasNoQueuedAdds = collectionInstance.endRead();
|
final boolean hasNoQueuedAdds = collectionInstance.endRead();
|
||||||
final SharedSessionContractImplementor session = executionContext.getSession();
|
final SharedSessionContractImplementor session = executionContext.getSession();
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
||||||
final CollectionPersister collectionDescriptor = getCollectionDescriptor();
|
final CollectionPersister collectionDescriptor = getCollectionDescriptor();
|
||||||
|
|
||||||
ResultsHelper.finalizeCollectionLoading(
|
ResultsHelper.finalizeCollectionLoading(
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.internal;
|
|
||||||
|
|
||||||
import org.hibernate.sql.results.spi.RowTransformer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Andrea Boriero
|
|
||||||
*/
|
|
||||||
public class RowTransformerDatabaseSnapshotImpl<T> implements RowTransformer<T> {
|
|
||||||
/**
|
|
||||||
* Singleton access
|
|
||||||
*/
|
|
||||||
public static final RowTransformerDatabaseSnapshotImpl INSTANCE = new RowTransformerDatabaseSnapshotImpl();
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T> RowTransformerDatabaseSnapshotImpl<T> instance() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private RowTransformerDatabaseSnapshotImpl() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public T transformRow(Object[] row) {
|
|
||||||
return (T) row;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -39,7 +39,7 @@ public class StandardRowReader<T> implements RowReader<T> {
|
||||||
private final Initializer<InitializerData>[] sortedForResolveInstance;
|
private final Initializer<InitializerData>[] sortedForResolveInstance;
|
||||||
private final InitializerData[] sortedForResolveInstanceData;
|
private final InitializerData[] sortedForResolveInstanceData;
|
||||||
private final boolean hasCollectionInitializers;
|
private final boolean hasCollectionInitializers;
|
||||||
private final RowTransformer<T> rowTransformer;
|
private final @Nullable RowTransformer<T> rowTransformer;
|
||||||
private final Class<T> domainResultJavaType;
|
private final Class<T> domainResultJavaType;
|
||||||
|
|
||||||
private final ComponentType componentType;
|
private final ComponentType componentType;
|
||||||
|
@ -78,7 +78,11 @@ public class StandardRowReader<T> implements RowReader<T> {
|
||||||
this.sortedForResolveInstance = (Initializer<InitializerData>[]) sortedForResolveInitializers;
|
this.sortedForResolveInstance = (Initializer<InitializerData>[]) sortedForResolveInitializers;
|
||||||
this.sortedForResolveInstanceData = new InitializerData[sortedForResolveInstance.length];
|
this.sortedForResolveInstanceData = new InitializerData[sortedForResolveInstance.length];
|
||||||
this.hasCollectionInitializers = hasCollectionInitializers;
|
this.hasCollectionInitializers = hasCollectionInitializers;
|
||||||
this.rowTransformer = rowTransformer;
|
this.rowTransformer = rowTransformer == RowTransformerArrayImpl.INSTANCE && resultAssemblers.length != 1
|
||||||
|
|| rowTransformer == RowTransformerStandardImpl.INSTANCE
|
||||||
|
|| rowTransformer == RowTransformerSingularReturnImpl.INSTANCE && resultAssemblers.length == 1
|
||||||
|
? null
|
||||||
|
: rowTransformer;
|
||||||
this.domainResultJavaType = domainResultJavaType;
|
this.domainResultJavaType = domainResultJavaType;
|
||||||
if ( domainResultJavaType == null
|
if ( domainResultJavaType == null
|
||||||
|| domainResultJavaType == Object[].class
|
|| domainResultJavaType == Object[].class
|
||||||
|
@ -136,6 +140,32 @@ public class StandardRowReader<T> implements RowReader<T> {
|
||||||
public T readRow(RowProcessingState rowProcessingState) {
|
public T readRow(RowProcessingState rowProcessingState) {
|
||||||
coordinateInitializers( rowProcessingState );
|
coordinateInitializers( rowProcessingState );
|
||||||
|
|
||||||
|
final T result;
|
||||||
|
if ( componentType != ComponentType.OBJECT ) {
|
||||||
|
result = readPrimitiveRow( 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finishUpRow();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private T readPrimitiveRow(RowProcessingState rowProcessingState) {
|
||||||
// The following is ugly, but unfortunately necessary to not hurt performance.
|
// The following is ugly, but unfortunately necessary to not hurt performance.
|
||||||
// This implementation was micro-benchmarked and discussed with Francesco Nigro,
|
// This implementation was micro-benchmarked and discussed with Francesco Nigro,
|
||||||
// who hinted that using this style instead of the reflective Array.getLength(), Array.set()
|
// who hinted that using this style instead of the reflective Array.getLength(), Array.set()
|
||||||
|
@ -143,110 +173,57 @@ public class StandardRowReader<T> implements RowReader<T> {
|
||||||
switch ( componentType ) {
|
switch ( componentType ) {
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
final boolean[] resultBooleanRow = new boolean[resultAssemblers.length];
|
final boolean[] resultBooleanRow = new boolean[resultAssemblers.length];
|
||||||
|
|
||||||
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
||||||
final DomainResultAssembler assembler = resultAssemblers[i];
|
resultBooleanRow[i] = (boolean) resultAssemblers[i].assemble( rowProcessingState );
|
||||||
resultBooleanRow[i] = (boolean) assembler.assemble( rowProcessingState );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afterRow( rowProcessingState );
|
|
||||||
|
|
||||||
return (T) resultBooleanRow;
|
return (T) resultBooleanRow;
|
||||||
case BYTE:
|
case BYTE:
|
||||||
final byte[] resultByteRow = new byte[resultAssemblers.length];
|
final byte[] resultByteRow = new byte[resultAssemblers.length];
|
||||||
|
|
||||||
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
||||||
final DomainResultAssembler assembler = resultAssemblers[i];
|
resultByteRow[i] = (byte) resultAssemblers[i].assemble( rowProcessingState );
|
||||||
resultByteRow[i] = (byte) assembler.assemble( rowProcessingState );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afterRow( rowProcessingState );
|
|
||||||
|
|
||||||
return (T) resultByteRow;
|
return (T) resultByteRow;
|
||||||
case CHAR:
|
case CHAR:
|
||||||
final char[] resultCharRow = new char[resultAssemblers.length];
|
final char[] resultCharRow = new char[resultAssemblers.length];
|
||||||
|
|
||||||
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
||||||
final DomainResultAssembler assembler = resultAssemblers[i];
|
resultCharRow[i] = (char) resultAssemblers[i].assemble( rowProcessingState );
|
||||||
resultCharRow[i] = (char) assembler.assemble( rowProcessingState );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afterRow( rowProcessingState );
|
|
||||||
|
|
||||||
return (T) resultCharRow;
|
return (T) resultCharRow;
|
||||||
case SHORT:
|
case SHORT:
|
||||||
final short[] resultShortRow = new short[resultAssemblers.length];
|
final short[] resultShortRow = new short[resultAssemblers.length];
|
||||||
|
|
||||||
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
||||||
final DomainResultAssembler assembler = resultAssemblers[i];
|
resultShortRow[i] = (short) resultAssemblers[i].assemble( rowProcessingState );
|
||||||
resultShortRow[i] = (short) assembler.assemble( rowProcessingState );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afterRow( rowProcessingState );
|
|
||||||
|
|
||||||
return (T) resultShortRow;
|
return (T) resultShortRow;
|
||||||
case INT:
|
case INT:
|
||||||
final int[] resultIntRow = new int[resultAssemblers.length];
|
final int[] resultIntRow = new int[resultAssemblers.length];
|
||||||
|
|
||||||
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
||||||
final DomainResultAssembler assembler = resultAssemblers[i];
|
resultIntRow[i] = (int) resultAssemblers[i].assemble( rowProcessingState );
|
||||||
resultIntRow[i] = (int) assembler.assemble( rowProcessingState );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afterRow( rowProcessingState );
|
|
||||||
|
|
||||||
return (T) resultIntRow;
|
return (T) resultIntRow;
|
||||||
case LONG:
|
case LONG:
|
||||||
final long[] resultLongRow = new long[resultAssemblers.length];
|
final long[] resultLongRow = new long[resultAssemblers.length];
|
||||||
|
|
||||||
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
||||||
final DomainResultAssembler assembler = resultAssemblers[i];
|
resultLongRow[i] = (long) resultAssemblers[i].assemble( rowProcessingState );
|
||||||
resultLongRow[i] = (long) assembler.assemble( rowProcessingState );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afterRow( rowProcessingState );
|
|
||||||
|
|
||||||
return (T) resultLongRow;
|
return (T) resultLongRow;
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
final float[] resultFloatRow = new float[resultAssemblers.length];
|
final float[] resultFloatRow = new float[resultAssemblers.length];
|
||||||
|
|
||||||
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
||||||
final DomainResultAssembler assembler = resultAssemblers[i];
|
resultFloatRow[i] = (float) resultAssemblers[i].assemble( rowProcessingState );
|
||||||
resultFloatRow[i] = (float) assembler.assemble( rowProcessingState );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afterRow( rowProcessingState );
|
|
||||||
|
|
||||||
return (T) resultFloatRow;
|
return (T) resultFloatRow;
|
||||||
case DOUBLE:
|
case DOUBLE:
|
||||||
final double[] resultDoubleRow = new double[resultAssemblers.length];
|
final double[] resultDoubleRow = new double[resultAssemblers.length];
|
||||||
|
|
||||||
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
||||||
final DomainResultAssembler assembler = resultAssemblers[i];
|
resultDoubleRow[i] = (double) resultAssemblers[i].assemble( rowProcessingState );
|
||||||
resultDoubleRow[i] = (double) assembler.assemble( rowProcessingState );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afterRow( rowProcessingState );
|
|
||||||
|
|
||||||
return (T) resultDoubleRow;
|
return (T) resultDoubleRow;
|
||||||
default:
|
default:
|
||||||
final Object[] resultRow = (Object[]) Array.newInstance( resultElementClass, resultAssemblers.length );
|
throw new AssertionError( "Object should be handled specially" );
|
||||||
|
|
||||||
for ( int i = 0; i < resultAssemblers.length; i++ ) {
|
|
||||||
final DomainResultAssembler assembler = resultAssemblers[i];
|
|
||||||
resultRow[i] = assembler.assemble( rowProcessingState );
|
|
||||||
}
|
|
||||||
|
|
||||||
afterRow( rowProcessingState );
|
|
||||||
|
|
||||||
return rowTransformer.transformRow( resultRow );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void afterRow(RowProcessingState rowProcessingState) {
|
|
||||||
finishUpRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void finishUpRow() {
|
private void finishUpRow() {
|
||||||
for ( InitializerData data : initializersData ) {
|
for ( InitializerData data : initializersData ) {
|
||||||
data.setState( Initializer.State.UNINITIALIZED );
|
data.setState( Initializer.State.UNINITIALIZED );
|
||||||
|
|
|
@ -105,7 +105,7 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Results<R> {
|
private static class Results<R> {
|
||||||
private final List<R> results;
|
private final ArrayList<R> results;
|
||||||
private final JavaType<R> resultJavaType;
|
private final JavaType<R> resultJavaType;
|
||||||
|
|
||||||
public Results(JavaType<R> resultJavaType, int initialSize) {
|
public Results(JavaType<R> resultJavaType, int initialSize) {
|
||||||
|
@ -188,37 +188,17 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
|
||||||
results = new Results<>( domainResultJavaType, initialCollectionSize );
|
results = new Results<>( domainResultJavaType, initialCollectionSize );
|
||||||
}
|
}
|
||||||
|
|
||||||
int readRows = 0;
|
final int readRows;
|
||||||
if ( uniqueSemantic == UniqueSemantic.FILTER
|
if ( uniqueSemantic == UniqueSemantic.FILTER
|
||||||
|| uniqueSemantic == UniqueSemantic.ASSERT && rowReader.hasCollectionInitializers()
|
|| uniqueSemantic == UniqueSemantic.ASSERT && rowReader.hasCollectionInitializers()
|
||||||
|| uniqueSemantic == UniqueSemantic.ALLOW && isEntityResultType ) {
|
|| uniqueSemantic == UniqueSemantic.ALLOW && isEntityResultType ) {
|
||||||
while ( rowProcessingState.next() ) {
|
readRows = readUnique( rowProcessingState, rowReader, results );
|
||||||
final boolean added = results.addUnique( rowReader.readRow( rowProcessingState ) );
|
|
||||||
rowProcessingState.finishRowProcessing( added );
|
|
||||||
readRows++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ( uniqueSemantic == UniqueSemantic.ASSERT ) {
|
else if ( uniqueSemantic == UniqueSemantic.ASSERT ) {
|
||||||
while ( rowProcessingState.next() ) {
|
readRows = readUniqueAssert( rowProcessingState, rowReader, results );
|
||||||
if ( !results.addUnique( rowReader.readRow( rowProcessingState ) ) ) {
|
|
||||||
throw new HibernateException(
|
|
||||||
String.format(
|
|
||||||
Locale.ROOT,
|
|
||||||
"Duplicate row was found and `%s` was specified",
|
|
||||||
UniqueSemantic.ASSERT
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
rowProcessingState.finishRowProcessing( true );
|
|
||||||
readRows++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
while ( rowProcessingState.next() ) {
|
readRows = read( rowProcessingState, rowReader, results );
|
||||||
results.add( rowReader.readRow( rowProcessingState ) );
|
|
||||||
rowProcessingState.finishRowProcessing( true );
|
|
||||||
readRows++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rowReader.finishUp( rowProcessingState );
|
rowReader.finishUp( rowProcessingState );
|
||||||
|
@ -260,6 +240,53 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
|
||||||
throw new IllegalStateException( "Should not reach this" );
|
throw new IllegalStateException( "Should not reach this" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static <R> int read(
|
||||||
|
RowProcessingStateStandardImpl rowProcessingState,
|
||||||
|
RowReader<R> rowReader,
|
||||||
|
Results<R> results) {
|
||||||
|
int readRows = 0;
|
||||||
|
while ( rowProcessingState.next() ) {
|
||||||
|
results.add( rowReader.readRow( rowProcessingState ) );
|
||||||
|
rowProcessingState.finishRowProcessing( true );
|
||||||
|
readRows++;
|
||||||
|
}
|
||||||
|
return readRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <R> int readUniqueAssert(
|
||||||
|
RowProcessingStateStandardImpl rowProcessingState,
|
||||||
|
RowReader<R> rowReader,
|
||||||
|
Results<R> results) {
|
||||||
|
int readRows = 0;
|
||||||
|
while ( rowProcessingState.next() ) {
|
||||||
|
if ( !results.addUnique( rowReader.readRow( rowProcessingState ) ) ) {
|
||||||
|
throw new HibernateException(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"Duplicate row was found and `%s` was specified",
|
||||||
|
UniqueSemantic.ASSERT
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
rowProcessingState.finishRowProcessing( true );
|
||||||
|
readRows++;
|
||||||
|
}
|
||||||
|
return readRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <R> int readUnique(
|
||||||
|
RowProcessingStateStandardImpl rowProcessingState,
|
||||||
|
RowReader<R> rowReader,
|
||||||
|
Results<R> results) {
|
||||||
|
int readRows = 0;
|
||||||
|
while ( rowProcessingState.next() ) {
|
||||||
|
final boolean added = results.addUnique( rowReader.readRow( rowProcessingState ) );
|
||||||
|
rowProcessingState.finishRowProcessing( added );
|
||||||
|
readRows++;
|
||||||
|
}
|
||||||
|
return readRows;
|
||||||
|
}
|
||||||
|
|
||||||
private JavaType<R> resolveDomainResultJavaType(
|
private JavaType<R> resolveDomainResultJavaType(
|
||||||
Class<R> domainResultResultJavaType,
|
Class<R> domainResultResultJavaType,
|
||||||
List<@Nullable JavaType<?>> resultJavaTypes,
|
List<@Nullable JavaType<?>> resultJavaTypes,
|
||||||
|
|
Loading…
Reference in New Issue