HHH-17202 Fix ArrayStoreException for single field id class entity collection batch loading

This commit is contained in:
Christian Beikov 2023-09-14 10:35:18 +02:00
parent fc65f98aa2
commit 3eb324f714
2 changed files with 36 additions and 14 deletions

View File

@ -14,7 +14,10 @@ import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.loader.ast.spi.CollectionBatchLoader; import org.hibernate.loader.ast.spi.CollectionBatchLoader;
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.ValuedModelPart;
import org.hibernate.metamodel.mapping.internal.IdClassEmbeddable;
import org.hibernate.sql.results.internal.ResultsHelper; import org.hibernate.sql.results.internal.ResultsHelper;
import java.lang.reflect.Array; import java.lang.reflect.Array;
@ -127,8 +130,10 @@ public abstract class AbstractCollectionBatchLoader implements CollectionBatchLo
Object[] resolveKeysToInitialize(Object keyBeingLoaded, SharedSessionContractImplementor session) { Object[] resolveKeysToInitialize(Object keyBeingLoaded, SharedSessionContractImplementor session) {
final int length = getDomainBatchSize(); final int length = getDomainBatchSize();
final Class<?> keyType = getLoadable().getKeyDescriptor().getJavaType().getJavaTypeClass(); final Object[] keysToInitialize = (Object[]) Array.newInstance(
final Object[] keysToInitialize = (Object[]) Array.newInstance( keyType, length ); getKeyType( getLoadable().getKeyDescriptor().getKeyPart() ),
length
);
session.getPersistenceContextInternal().getBatchFetchQueue() session.getPersistenceContextInternal().getBatchFetchQueue()
.collectBatchLoadableCollectionKeys( .collectBatchLoadableCollectionKeys(
length, length,
@ -140,4 +145,15 @@ public abstract class AbstractCollectionBatchLoader implements CollectionBatchLo
return trimIdBatch( length, keysToInitialize ); return trimIdBatch( length, keysToInitialize );
} }
protected Class<?> getKeyType(ValuedModelPart keyPart) {
if ( keyPart instanceof NonAggregatedIdentifierMapping ) {
final IdClassEmbeddable idClassEmbeddable = ( (NonAggregatedIdentifierMapping) keyPart ).getIdClassEmbeddable();
if ( idClassEmbeddable != null ) {
return idClassEmbeddable.getMappedJavaType().getJavaTypeClass();
}
}
return keyPart.getJavaType().getJavaTypeClass();
}
} }

View File

@ -19,7 +19,10 @@ import org.hibernate.loader.ast.spi.CollectionBatchLoader;
import org.hibernate.loader.ast.spi.SqlArrayMultiKeyLoader; import org.hibernate.loader.ast.spi.SqlArrayMultiKeyLoader;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.ValuedModelPart;
import org.hibernate.metamodel.mapping.internal.IdClassEmbeddable;
import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryOptions;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement; import org.hibernate.sql.ast.tree.select.SelectStatement;
@ -45,6 +48,7 @@ import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LO
public class CollectionBatchLoaderArrayParam public class CollectionBatchLoaderArrayParam
extends AbstractCollectionBatchLoader extends AbstractCollectionBatchLoader
implements SqlArrayMultiKeyLoader { implements SqlArrayMultiKeyLoader {
private final Class<?> keyDomainType;
private final JdbcMapping arrayJdbcMapping; private final JdbcMapping arrayJdbcMapping;
private final JdbcParameter jdbcParameter; private final JdbcParameter jdbcParameter;
private final SelectStatement sqlSelect; private final SelectStatement sqlSelect;
@ -66,16 +70,18 @@ public class CollectionBatchLoaderArrayParam
} }
final ForeignKeyDescriptor keyDescriptor = getLoadable().getKeyDescriptor(); final ForeignKeyDescriptor keyDescriptor = getLoadable().getKeyDescriptor();
final Class<?> keyType = keyDescriptor.getJavaType().getJavaTypeClass(); final JdbcMapping jdbcMapping = keyDescriptor.getSingleJdbcMapping();
final Class<?> arrayClass = Array.newInstance( keyType, 0 ).getClass(); final Class<?> jdbcArrayClass = Array.newInstance( jdbcMapping.getJdbcJavaType().getJavaTypeClass(), 0 )
.getClass();
keyDomainType = getKeyType( keyDescriptor.getKeyPart() );
final BasicType<?> arrayBasicType = getSessionFactory().getTypeConfiguration() final BasicType<?> arrayBasicType = getSessionFactory().getTypeConfiguration()
.getBasicTypeRegistry() .getBasicTypeRegistry()
.getRegisteredType( arrayClass ); .getRegisteredType( jdbcArrayClass );
arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping(
arrayBasicType, arrayBasicType,
keyDescriptor.getSingleJdbcMapping(), jdbcMapping,
arrayClass, jdbcArrayClass,
getSessionFactory() getSessionFactory()
); );
@ -95,7 +101,6 @@ public class CollectionBatchLoaderArrayParam
.buildSelectTranslator( getSessionFactory(), sqlSelect ) .buildSelectTranslator( getSessionFactory(), sqlSelect )
.translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE ); .translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE );
} }
@Override @Override
public PersistentCollection<?> load(Object keyBeingLoaded, SharedSessionContractImplementor session) { public PersistentCollection<?> load(Object keyBeingLoaded, SharedSessionContractImplementor session) {
final ForeignKeyDescriptor keyDescriptor = getLoadable().getKeyDescriptor(); final ForeignKeyDescriptor keyDescriptor = getLoadable().getKeyDescriptor();
@ -122,13 +127,14 @@ public class CollectionBatchLoaderArrayParam
final int length = getDomainBatchSize(); final int length = getDomainBatchSize();
final Object[] keysToInitialize = (Object[]) Array.newInstance( final Object[] keysToInitialize = (Object[]) Array.newInstance(
keyDescriptor.getSingleJdbcMapping().getJdbcJavaType().getJavaTypeClass(), jdbcParameter.getExpressionType()
length .getSingleJdbcMapping()
); .getJdbcJavaType()
final Object[] embeddedKeys = (Object[]) Array.newInstance( .getJavaTypeClass()
keyDescriptor.getJavaType().getJavaTypeClass(), .getComponentType(),
length length
); );
final Object[] embeddedKeys = (Object[]) Array.newInstance( keyDomainType, length );
session.getPersistenceContextInternal().getBatchFetchQueue() session.getPersistenceContextInternal().getBatchFetchQueue()
.collectBatchLoadableCollectionKeys( .collectBatchLoadableCollectionKeys(
length, length,
@ -157,7 +163,7 @@ public class CollectionBatchLoaderArrayParam
} }
final CollectionKey collectionKey = new CollectionKey( final CollectionKey collectionKey = new CollectionKey(
getLoadable().getCollectionDescriptor(), getLoadable().getCollectionDescriptor(),
keysToInitialize keyBeingLoaded
); );
return session.getPersistenceContext().getCollection( collectionKey ); return session.getPersistenceContext().getCollection( collectionKey );
} }