HHH-16471 Entities serialized in QueryKey causes java.lang.ClassCastException

This commit is contained in:
Andrea Boriero 2023-04-21 11:28:16 +02:00 committed by Andrea Boriero
parent b1a4890c3e
commit add6d84310
2 changed files with 27 additions and 15 deletions

View File

@ -1017,7 +1017,7 @@ public interface EntityPersister extends EntityMappingType, RootTableGroupProduc
MutableCacheKeyBuilder cacheKey, MutableCacheKeyBuilder cacheKey,
Object value, Object value,
SharedSessionContractImplementor session) { SharedSessionContractImplementor session) {
getIdentifierMapping().addToCacheKey( cacheKey, value, session ); getIdentifierMapping().addToCacheKey( cacheKey, getIdentifier( value, session ), session );
} }
BytecodeEnhancementMetadata getInstrumentationMetadata(); BytecodeEnhancementMetadata getInstrumentationMetadata();

View File

@ -12,6 +12,7 @@ import java.util.IdentityHashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -22,8 +23,8 @@ import org.hibernate.cache.MutableCacheKeyBuilder;
import org.hibernate.cache.spi.QueryKey; import org.hibernate.cache.spi.QueryKey;
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.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.MappingModelExpressible; import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.query.BindableType;
import org.hibernate.query.QueryParameter; import org.hibernate.query.QueryParameter;
import org.hibernate.query.spi.ParameterMetadataImplementor; import org.hibernate.query.spi.ParameterMetadataImplementor;
import org.hibernate.query.spi.QueryParameterBinding; import org.hibernate.query.spi.QueryParameterBinding;
@ -169,9 +170,13 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
public QueryKey.ParameterBindingsMemento generateQueryKeyMemento(SharedSessionContractImplementor persistenceContext) { public QueryKey.ParameterBindingsMemento generateQueryKeyMemento(SharedSessionContractImplementor persistenceContext) {
final MutableCacheKeyImpl mutableCacheKey = new MutableCacheKeyImpl(parameterBindingMap.size()); final MutableCacheKeyImpl mutableCacheKey = new MutableCacheKeyImpl(parameterBindingMap.size());
for ( QueryParameterBinding<?> binding : parameterBindingMap.values() ) { for ( Map.Entry<QueryParameter<?>, QueryParameterBinding<?>> entry : parameterBindingMap.entrySet() ) {
final MappingModelExpressible<?> mappingType = determineMappingType( binding, persistenceContext ); final QueryParameterBinding<?> binding = entry.getValue();
assert mappingType instanceof JavaTypedExpressible; final MappingModelExpressible<?> mappingType = determineMappingType(
binding,
entry.getKey(),
persistenceContext
);
if ( binding.isMultiValued() ) { if ( binding.isMultiValued() ) {
for ( Object bindValue : binding.getBindValues() ) { for ( Object bindValue : binding.getBindValues() ) {
@ -188,26 +193,24 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
return mutableCacheKey.build(); return mutableCacheKey.build();
} }
private MappingModelExpressible<?> determineMappingType(QueryParameterBinding<?> binding, SharedSessionContractImplementor session) { private MappingModelExpressible<?> determineMappingType(final QueryParameterBinding<?> binding, final QueryParameter<?> queryParameter, final SharedSessionContractImplementor session) {
if ( binding.getBindType() != null ) { final BindableType<?> bindType = binding.getBindType();
if ( binding.getBindType() instanceof MappingModelExpressible) { if ( bindType != null ) {
if ( bindType instanceof MappingModelExpressible ) {
//noinspection unchecked //noinspection unchecked
return (MappingModelExpressible<Object>) binding.getBindType(); return (MappingModelExpressible<Object>) bindType;
} }
} }
final MappingModelExpressible<?> type = binding.getType(); final MappingModelExpressible<?> type = binding.getType();
if ( type != null ) { if ( type != null ) {
if ( type instanceof EntityMappingType ) {
return ( (EntityMappingType) type ).getIdentifierMapping();
}
return type; return type;
} }
final TypeConfiguration typeConfiguration = session.getFactory().getTypeConfiguration(); final TypeConfiguration typeConfiguration = session.getFactory().getTypeConfiguration();
if ( binding.getBindType() instanceof JavaTypedExpressible) { if ( bindType instanceof JavaTypedExpressible) {
final JavaTypedExpressible<?> javaTypedExpressible = (JavaTypedExpressible<?>) binding.getBindType(); final JavaTypedExpressible<?> javaTypedExpressible = (JavaTypedExpressible<?>) bindType;
final JavaType<?> jtd = javaTypedExpressible.getExpressibleJavaType(); final JavaType<?> jtd = javaTypedExpressible.getExpressibleJavaType();
if ( jtd.getJavaTypeClass() != null ) { if ( jtd.getJavaTypeClass() != null ) {
// avoid dynamic models // avoid dynamic models
@ -228,7 +231,16 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
else if ( binding.getBindValue() != null ) { else if ( binding.getBindValue() != null ) {
return typeConfiguration.getBasicTypeForJavaType( binding.getBindValue().getClass() ); return typeConfiguration.getBasicTypeForJavaType( binding.getBindValue().getClass() );
} }
return typeConfiguration.getBasicTypeForJavaType( binding.getBindType().getBindableJavaType() );
if ( bindType == null ) {
if ( queryParameter.getName() != null ) {
throw new QueryException( "Cannot determine mapping type for parameter : " + queryParameter.getName() );
}
else {
throw new QueryException( "Cannot determine mapping type for parameter : " + queryParameter.getPosition() );
}
}
return typeConfiguration.getBasicTypeForJavaType( bindType.getBindableJavaType() );
} }
private static class MutableCacheKeyImpl implements MutableCacheKeyBuilder { private static class MutableCacheKeyImpl implements MutableCacheKeyBuilder {