HHH-16372 Fix NPEs in some Bindable implementations that operate on values

This commit is contained in:
Christian Beikov 2023-03-25 15:30:45 +01:00
parent 7f7e4b5f6a
commit 71541679e8
12 changed files with 421 additions and 344 deletions

View File

@ -88,11 +88,6 @@ public abstract class AbstractCompositeIdentifierMapping
return getPartMappingType();
}
@Override
public JavaType<?> getJavaType() {
return getPartMappingType().getMappedJavaType();
}
@Override
public String getContainingTableExpression() {
return tableExpression;
@ -188,28 +183,36 @@ public abstract class AbstractCompositeIdentifierMapping
int span = 0;
final EmbeddableMappingType embeddableTypeDescriptor = getEmbeddableTypeDescriptor();
final int size = embeddableTypeDescriptor.getNumberOfAttributeMappings();
for ( int i = 0; i < size; i++ ) {
final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
if ( attributeMapping instanceof ToOneAttributeMapping ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
final ForeignKeyDescriptor fkDescriptor = toOneAttributeMapping.getForeignKeyDescriptor();
final Object identifier = fkDescriptor.getAssociationKeyFromSide(
o,
toOneAttributeMapping.getSideNature().inverse(),
session
);
span += fkDescriptor.forEachJdbcValue(
identifier,
span + offset,
x,
y,
valuesConsumer,
session
);
if ( value == null ) {
for ( int i = 0; i < size; i++ ) {
final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i );
span += attributeMapping.forEachJdbcValue( null, span + offset, x, y, valuesConsumer, session );
}
else {
span += attributeMapping.forEachJdbcValue( o, span + offset, x, y, valuesConsumer, session );
}
else {
for ( int i = 0; i < size; i++ ) {
final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
if ( attributeMapping instanceof ToOneAttributeMapping ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
final ForeignKeyDescriptor fkDescriptor = toOneAttributeMapping.getForeignKeyDescriptor();
final Object identifier = fkDescriptor.getAssociationKeyFromSide(
o,
toOneAttributeMapping.getSideNature().inverse(),
session
);
span += fkDescriptor.forEachJdbcValue(
identifier,
span + offset,
x,
y,
valuesConsumer,
session
);
}
else {
span += attributeMapping.forEachJdbcValue( o, span + offset, x, y, valuesConsumer, session );
}
}
}
return span;

View File

@ -21,6 +21,7 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.type.descriptor.java.JavaType;
/**
* Describes the mapping of an embeddable (composite).
@ -37,6 +38,11 @@ public interface EmbeddableValuedModelPart extends ValuedModelPart, Fetchable, F
return getEmbeddableTypeDescriptor();
}
@Override
default JavaType<?> getJavaType() {
return getEmbeddableTypeDescriptor().getJavaType();
}
@Override
default ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
return getEmbeddableTypeDescriptor().findSubPart( name, treatTargetType );
@ -83,6 +89,43 @@ public interface EmbeddableValuedModelPart extends ValuedModelPart, Fetchable, F
return getEmbeddableTypeDescriptor().forEachJdbcValue( value, offset, x, y, valuesConsumer, session );
}
@Override
default <X, Y> int breakDownJdbcValues(
Object domainValue,
int offset,
X x,
Y y,
JdbcValueBiConsumer<X, Y> valueConsumer,
SharedSessionContractImplementor session) {
return getEmbeddableTypeDescriptor().breakDownJdbcValues( domainValue, offset, x, y, valueConsumer, session );
}
@Override
default <X, Y> int decompose(
Object domainValue,
int offset,
X x,
Y y,
JdbcValueBiConsumer<X, Y> valueConsumer,
SharedSessionContractImplementor session) {
return getEmbeddableTypeDescriptor().decompose( domainValue, offset, x, y, valueConsumer, session );
}
@Override
default int getNumberOfFetchables() {
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
}
@Override
default Fetchable getFetchable(int position) {
return getEmbeddableTypeDescriptor().getFetchable( position );
}
@Override
default int getSelectableIndex(String selectableName) {
return getEmbeddableTypeDescriptor().getSelectableIndex( selectableName );
}
@Override
default SelectableMapping getSelectable(int columnIndex) {
return getEmbeddableTypeDescriptor().getSelectable( columnIndex );
@ -93,6 +136,21 @@ public interface EmbeddableValuedModelPart extends ValuedModelPart, Fetchable, F
return getEmbeddableTypeDescriptor().forEachSelectable( offset, consumer );
}
@Override
default void forEachInsertable(SelectableConsumer consumer) {
getEmbeddableTypeDescriptor().forEachInsertable( 0, consumer );
}
@Override
default void forEachUpdatable(SelectableConsumer consumer) {
getEmbeddableTypeDescriptor().forEachUpdatable( 0, consumer );
}
@Override
default boolean hasPartitionedSelectionMapping() {
return getEmbeddableTypeDescriptor().hasPartitionedSelectionMapping();
}
@Override
default <X, Y> int forEachDisassembledJdbcValue(
Object value,

View File

@ -574,8 +574,35 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
forEachAttributeMapping( consumer );
}
@Override
public <X, Y> int breakDownJdbcValues(
Object domainValue,
int offset,
X x,
Y y,
JdbcValueBiConsumer<X, Y> valueConsumer, SharedSessionContractImplementor session) {
int span = 0;
if ( domainValue == null ) {
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attribute = attributeMappings.get( i );
span += attribute.breakDownJdbcValues( null, offset + span, x, y, valueConsumer, session );
}
}
else {
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attribute = attributeMappings.get( i );
final Object attributeValue = attribute.getValue( domainValue );
span += attribute.breakDownJdbcValues( attributeValue, offset + span, x, y, valueConsumer, session );
}
}
return span;
}
@Override
public Object disassemble(Object value, SharedSessionContractImplementor session) {
if ( value == null ) {
return null;
}
final int size = attributeMappings.size();
final Object[] result = new Object[ size ];
for ( int i = 0; i < size; i++ ) {
@ -590,9 +617,16 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
@Override
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
final int size = attributeMappings.size();
for ( int i = 0; i < size; i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
attributeMapping.addToCacheKey( cacheKey, attributeMapping.getValue( value ), session );
if ( value == null ) {
for ( int i = 0; i < size; i++ ) {
attributeMappings.get( i ).addToCacheKey( cacheKey, null, session );
}
}
else {
for ( int i = 0; i < size; i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
attributeMapping.addToCacheKey( cacheKey, attributeMapping.getValue( value ), session );
}
}
}
@ -604,11 +638,19 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
Y y,
JdbcValuesBiConsumer<X, Y> valuesConsumer,
SharedSessionContractImplementor session) {
final Object[] values = (Object[]) value;
int span = 0;
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping mapping = attributeMappings.get( i );
span += mapping.forEachDisassembledJdbcValue( values[i], span + offset, x, y, valuesConsumer, session );
if ( value == null ) {
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping mapping = attributeMappings.get( i );
span += mapping.forEachDisassembledJdbcValue( null, span + offset, x, y, valuesConsumer, session );
}
}
else {
final Object[] values = (Object[]) value;
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping mapping = attributeMappings.get( i );
span += mapping.forEachDisassembledJdbcValue( values[i], span + offset, x, y, valuesConsumer, session );
}
}
return span;
}
@ -622,14 +664,24 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
JdbcValuesBiConsumer<X, Y> valuesConsumer,
SharedSessionContractImplementor session) {
int span = 0;
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
if ( attributeMapping instanceof PluralAttributeMapping ) {
continue;
if ( value == null ) {
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
if ( attributeMapping instanceof PluralAttributeMapping ) {
continue;
}
span += attributeMapping.forEachJdbcValue( null, span + offset, x, y, valuesConsumer, session );
}
}
else {
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
if ( attributeMapping instanceof PluralAttributeMapping ) {
continue;
}
final Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
span += attributeMapping.forEachJdbcValue( o, span + offset, x, y, valuesConsumer, session );
}
final Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
span += attributeMapping.forEachJdbcValue( o, span + offset, x, y, valuesConsumer, session );
}
return span;
}

View File

@ -326,16 +326,23 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
for ( int i = 0; i < attributes.size(); i++ ) {
span += attributes.get( i ).breakDownJdbcValues( null, offset + span, x, y, valueConsumer, session );
}
return span;
}
else {
assert domainValue instanceof Object[];
assert domainValue instanceof Object[];
final Object[] values = (Object[]) domainValue;
assert values.length == attributes.size();
final Object[] values = (Object[]) domainValue;
assert values.length == attributes.size();
for ( int i = 0; i < attributes.size(); i++ ) {
span += attributes.get( i ).breakDownJdbcValues( values[ i ], offset + span, x, y, valueConsumer, session );
for ( int i = 0; i < attributes.size(); i++ ) {
span += attributes.get( i ).breakDownJdbcValues(
values[i],
offset + span,
x,
y,
valueConsumer,
session
);
}
}
return span;
}
@ -379,6 +386,9 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
@Override
public Object disassemble(Object value, SharedSessionContractImplementor session) {
if ( value == null ) {
return null;
}
assert value instanceof Object[];
final Object[] incoming = (Object[]) value;
@ -396,13 +406,20 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
@Override
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
assert value instanceof Object[];
if ( value == null ) {
for ( int i = 0; i < attributes.size(); i++ ) {
attributes.get( i ).addToCacheKey( cacheKey, null, session );
}
}
else {
assert value instanceof Object[];
final Object[] values = (Object[]) value;
assert values.length == attributes.size();
final Object[] values = (Object[]) value;
assert values.length == attributes.size();
for ( int i = 0; i < attributes.size(); i++ ) {
attributes.get( i ).addToCacheKey( cacheKey, values[i], session );
for ( int i = 0; i < attributes.size(); i++ ) {
attributes.get( i ).addToCacheKey( cacheKey, values[i], session );
}
}
}
@ -414,14 +431,36 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
Y y,
JdbcValuesBiConsumer<X, Y> valuesConsumer,
SharedSessionContractImplementor session) {
assert value instanceof Object[];
final Object[] incoming = (Object[]) value;
assert incoming.length == attributes.size();
int span = 0;
for ( int i = 0; i < attributes.size(); i++ ) {
final SingularAttributeMapping attribute = attributes.get( i );
span += attribute.forEachDisassembledJdbcValue( incoming[ i ], span + offset, x, y, valuesConsumer, session );
if ( value == null ) {
for ( int i = 0; i < attributes.size(); i++ ) {
final SingularAttributeMapping attribute = attributes.get( i );
span += attribute.forEachDisassembledJdbcValue(
null,
span + offset,
x,
y,
valuesConsumer,
session
);
}
}
else {
assert value instanceof Object[];
final Object[] incoming = (Object[]) value;
assert incoming.length == attributes.size();
for ( int i = 0; i < attributes.size(); i++ ) {
final SingularAttributeMapping attribute = attributes.get( i );
span += attribute.forEachDisassembledJdbcValue(
incoming[i],
span + offset,
x,
y,
valuesConsumer,
session
);
}
}
return span;
}
@ -434,15 +473,23 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
Y y,
JdbcValuesBiConsumer<X, Y> valuesConsumer,
SharedSessionContractImplementor session) {
assert value instanceof Object[];
final Object[] incoming = (Object[]) value;
assert incoming.length == attributes.size();
int span = 0;
for ( int i = 0; i < attributes.size(); i++ ) {
final SingularAttributeMapping attribute = attributes.get( i );
span += attribute.forEachJdbcValue( incoming[ i ], span + offset, x, y, valuesConsumer, session );
if ( value == null ) {
for ( int i = 0; i < attributes.size(); i++ ) {
final SingularAttributeMapping attribute = attributes.get( i );
span += attribute.forEachJdbcValue( null, span + offset, x, y, valuesConsumer, session );
}
}
else {
assert value instanceof Object[];
final Object[] incoming = (Object[]) value;
assert incoming.length == attributes.size();
for ( int i = 0; i < attributes.size(); i++ ) {
final SingularAttributeMapping attribute = attributes.get( i );
span += attribute.forEachJdbcValue( incoming[i], span + offset, x, y, valuesConsumer, session );
}
}
return span;
}

View File

@ -240,18 +240,20 @@ public class DiscriminatedAssociationAttributeMapping
@Override
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
if ( value == null ) {
return ;
cacheKey.addValue( null );
cacheKey.addHashCode( 0 );
}
else {
final EntityMappingType concreteMappingType = determineConcreteType( value, session );
final EntityMappingType concreteMappingType = determineConcreteType( value, session );
final Object discriminator = discriminatorMapping
.getModelPart()
.resolveDiscriminatorForEntityType( concreteMappingType );
discriminatorMapping.getDiscriminatorPart().addToCacheKey( cacheKey, discriminator, session );
final Object discriminator = discriminatorMapping
.getModelPart()
.resolveDiscriminatorForEntityType( concreteMappingType );
discriminatorMapping.getDiscriminatorPart().addToCacheKey( cacheKey, discriminator, session );
final EntityIdentifierMapping identifierMapping = concreteMappingType.getIdentifierMapping();
identifierMapping.addToCacheKey( cacheKey, identifierMapping.getIdentifier( value ), session );
final EntityIdentifierMapping identifierMapping = concreteMappingType.getIdentifierMapping();
identifierMapping.addToCacheKey( cacheKey, identifierMapping.getIdentifier( value ), session );
}
}
private EntityMappingType determineConcreteType(Object entity, SharedSessionContractImplementor session) {
@ -290,7 +292,23 @@ public class DiscriminatedAssociationAttributeMapping
Y y,
JdbcValuesBiConsumer<X, Y> valuesConsumer,
SharedSessionContractImplementor session) {
if ( value != null ) {
if ( value == null ) {
valuesConsumer.consume(
offset,
x,
y,
null,
discriminatorMapping.getDiscriminatorPart().getJdbcMapping()
);
valuesConsumer.consume(
offset + 1,
x,
y,
null,
discriminatorMapping.getKeyPart().getJdbcMapping()
);
}
else {
if ( value.getClass().isArray() ) {
final Object[] values = (Object[]) value;
valuesConsumer.consume(

View File

@ -184,53 +184,6 @@ public class EmbeddedAttributeMapping
return parentInjectionAttributePropertyAccess;
}
@Override
public int compare(Object value1, Object value2) {
return super.compare( value1, value2 );
}
@Override
public int forEachSelectable(int offset, SelectableConsumer consumer) {
return getEmbeddableTypeDescriptor().forEachSelectable( offset, consumer );
}
@Override
public void forEachInsertable(SelectableConsumer consumer) {
getEmbeddableTypeDescriptor().forEachInsertable( 0, consumer );
}
@Override
public void forEachUpdatable(SelectableConsumer consumer) {
getEmbeddableTypeDescriptor().forEachUpdatable( 0, consumer );
}
@Override
public <X, Y> int breakDownJdbcValues(
Object domainValue,
int offset,
X x,
Y y,
JdbcValueBiConsumer<X, Y> valueConsumer,
SharedSessionContractImplementor session) {
return getEmbeddableTypeDescriptor().breakDownJdbcValues( domainValue, offset, x, y, valueConsumer, session );
}
@Override
public <X, Y> int decompose(
Object domainValue,
int offset,
X x,
Y y,
JdbcValueBiConsumer<X, Y> valueConsumer,
SharedSessionContractImplementor session) {
return getEmbeddableTypeDescriptor().decompose( domainValue, offset, x, y, valueConsumer, session );
}
@Override
public boolean hasPartitionedSelectionMapping() {
return getEmbeddableTypeDescriptor().hasPartitionedSelectionMapping();
}
@Override
public <T> DomainResult<T> createDomainResult(
NavigablePath navigablePath,
@ -343,20 +296,6 @@ public class EmbeddedAttributeMapping
return new SqlTuple( columnReferences, this );
}
@Override
public ModelPart findSubPart(
String name,
EntityMappingType treatTargetType) {
return getMappedType().findSubPart( name, treatTargetType );
}
@Override
public void visitSubParts(
Consumer<ModelPart> consumer,
EntityMappingType treatTargetType) {
getMappedType().visitSubParts( consumer, treatTargetType );
}
@Override
public TableGroupJoin createTableGroupJoin(
NavigablePath navigablePath,
@ -400,21 +339,6 @@ public class EmbeddedAttributeMapping
return getAttributeName();
}
@Override
public int getNumberOfFetchables() {
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
}
@Override
public Fetchable getFetchable(int position) {
return getEmbeddableTypeDescriptor().getFetchable( position );
}
@Override
public int getSelectableIndex(String selectableName) {
return getEmbeddableTypeDescriptor().getSelectableIndex( selectableName );
}
@Override
public String toString() {
return "EmbeddedAttributeMapping(" + navigableRole + ")@" + System.identityHashCode( this );

View File

@ -297,11 +297,6 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
embeddableMappingType.applySqlSelections( navigablePath, tableGroup, creationState, selectionConsumer );
}
@Override
public JavaType<?> getJavaType() {
return getEmbeddableTypeDescriptor().getJavaType();
}
@Override
public JavaType<?> getExpressibleJavaType() {
return getJavaType();
@ -317,32 +312,6 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
return collectionDescriptor.getAttributeMapping().findContainingEntityMapping();
}
@Override
public int getNumberOfFetchables() {
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
}
@Override
public Fetchable getFetchable(int position) {
return getEmbeddableTypeDescriptor().getFetchable( position );
}
@Override
public int forEachSelectable(int offset, SelectableConsumer consumer) {
return getEmbeddableTypeDescriptor().forEachSelectable( offset, consumer );
}
@Override
public <X, Y> int breakDownJdbcValues(
Object domainValue,
int offset,
X x,
Y y,
JdbcValueBiConsumer<X, Y> valueConsumer,
SharedSessionContractImplementor session) {
return getEmbeddableTypeDescriptor().breakDownJdbcValues( domainValue, offset, x, y, valueConsumer, session );
}
@Override
public FetchStyle getStyle() {
return FetchStyle.JOIN;
@ -353,9 +322,4 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
return FetchTiming.IMMEDIATE;
}
@Override
public boolean hasPartitionedSelectionMapping() {
return getEmbeddableTypeDescriptor().hasPartitionedSelectionMapping();
}
}

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.metamodel.mapping.internal;
import java.io.Serializable;
import java.util.function.BiConsumer;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
@ -110,17 +109,6 @@ public class EmbeddedIdentifierMappingImpl
return name;
}
@Override
public int getNumberOfFetchables() {
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
}
@Override
public Fetchable getFetchable(int position) {
return getEmbeddableTypeDescriptor().getFetchable( position );
}
@Override
public PropertyAccess getPropertyAccess() {
return propertyAccess;
@ -131,32 +119,4 @@ public class EmbeddedIdentifierMappingImpl
return name;
}
@Override
public <X, Y> int breakDownJdbcValues(
Object domainValue,
int offset,
X x,
Y y,
JdbcValueBiConsumer<X, Y> valueConsumer,
SharedSessionContractImplementor session) {
return getEmbeddableTypeDescriptor().breakDownJdbcValues( domainValue, offset, x, y, valueConsumer, session );
}
@Override
public <X, Y> int forEachDisassembledJdbcValue(
Object value,
int offset,
X x,
Y y,
JdbcValuesBiConsumer<X, Y> valuesConsumer,
SharedSessionContractImplementor session) {
return getEmbeddableTypeDescriptor().forEachDisassembledJdbcValue(
value,
offset,
x,
y,
valuesConsumer,
session
);
}
}

View File

@ -6,10 +6,8 @@
*/
package org.hibernate.metamodel.mapping.internal;
import java.io.Serializable;
import java.util.function.Consumer;
import org.hibernate.cache.MutableCacheKeyBuilder;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.EntityKey;
@ -288,49 +286,6 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
return idMapping.findContainingEntityMapping();
}
@Override
public <X, Y> int breakDownJdbcValues(
Object domainValue,
int offset,
X x,
Y y,
JdbcValueBiConsumer<X, Y> valueConsumer,
SharedSessionContractImplementor session) {
int span = 0;
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attribute = attributeMappings.get( i );
final Object attributeValue = attribute.getValue( domainValue );
span += attribute.breakDownJdbcValues( attributeValue, offset + span, x, y, valueConsumer, session );
}
return span;
}
@Override
public Object disassemble(Object value, SharedSessionContractImplementor session) {
// todo (6.0) : reduce to-one values to id here?
final Object[] result = new Object[ getNumberOfAttributeMappings() ];
for ( int i = 0; i < result.length; i++ ) {
final AttributeMapping attributeMapping = getAttributeMapping( i );
Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
result[i] = attributeMapping.disassemble( o, session );
}
return result;
}
@Override
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
if ( value == null ) {
return;
}
final Serializable[] result = new Serializable[ getNumberOfAttributeMappings() ];
for ( int i = 0; i < result.length; i++ ) {
final AttributeMapping attributeMapping = getAttributeMapping( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
attributeMapping.addToCacheKey( cacheKey, o, session );
}
}
@Override
public <X, Y> int forEachDisassembledJdbcValue(
Object value,

View File

@ -158,22 +158,6 @@ public class VirtualIdEmbeddable extends AbstractEmbeddableMapping implements Id
throw new UnsupportedOperationException();
}
@Override
public <X, Y> int breakDownJdbcValues(
Object domainValue,
int offset,
X x,
Y y,
JdbcValueBiConsumer<X, Y> valueConsumer, SharedSessionContractImplementor session) {
int span = 0;
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attribute = attributeMappings.get( i );
final Object attributeValue = attribute.getValue( domainValue );
span += attribute.breakDownJdbcValues( attributeValue, offset + span, x, y, valueConsumer, session );
}
return span;
}
@Override
public <X, Y> int decompose(
Object domainValue,

View File

@ -34,6 +34,9 @@ public class TupleMappingModelExpressible implements MappingModelExpressible {
@Override
public Object disassemble(Object value, SharedSessionContractImplementor session) {
if ( value == null ) {
return null;
}
final Object[] disassembled = new Object[components.length];
final Object[] array = (Object[]) value;
for ( int i = 0; i < components.length; i++ ) {
@ -45,10 +48,15 @@ public class TupleMappingModelExpressible implements MappingModelExpressible {
@Override
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
if ( value == null ) {
return;
for ( int i = 0; i < components.length; i++ ) {
components[i].addToCacheKey( cacheKey, null, session );
}
}
for ( int i = 0; i < components.length; i++ ) {
components[i].addToCacheKey( cacheKey, value, session );
else {
final Object[] array = (Object[]) value;
for ( int i = 0; i < components.length; i++ ) {
components[i].addToCacheKey( cacheKey, array[i], session );
}
}
}
@ -60,10 +68,31 @@ public class TupleMappingModelExpressible implements MappingModelExpressible {
Y y,
JdbcValuesBiConsumer<X, Y> valuesConsumer,
SharedSessionContractImplementor session) {
final Object[] values = (Object[]) value;
int span = 0;
for ( int i = 0; i < components.length; i++ ) {
span += components[i].forEachDisassembledJdbcValue( values[i], span + offset, x, y, valuesConsumer, session );
if ( value == null ) {
for ( int i = 0; i < components.length; i++ ) {
span += components[i].forEachDisassembledJdbcValue(
null,
span + offset,
x,
y,
valuesConsumer,
session
);
}
}
else {
final Object[] values = (Object[]) value;
for ( int i = 0; i < components.length; i++ ) {
span += components[i].forEachDisassembledJdbcValue(
values[i],
span + offset,
x,
y,
valuesConsumer,
session
);
}
}
return span;
}
@ -76,15 +105,27 @@ public class TupleMappingModelExpressible implements MappingModelExpressible {
Y y,
JdbcValuesBiConsumer<X, Y> valuesConsumer,
SharedSessionContractImplementor session) {
final Object[] values = (Object[]) value;
int span = 0;
for ( int i = 0; i < components.length; i++ ) {
span += components[i].forEachDisassembledJdbcValue(
components[i].disassemble( values[i], session ),
span + offset,
x, y, valuesConsumer,
session
);
if ( value == null ) {
for ( int i = 0; i < components.length; i++ ) {
span += components[i].forEachDisassembledJdbcValue(
components[i].disassemble( null, session ),
span + offset,
x, y, valuesConsumer,
session
);
}
}
else {
final Object[] values = (Object[]) value;
for ( int i = 0; i < components.length; i++ ) {
span += components[i].forEachDisassembledJdbcValue(
components[i].disassemble( values[i], session ),
span + offset,
x, y, valuesConsumer,
session
);
}
}
return span;
}

View File

@ -56,6 +56,7 @@ import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchOptions;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableResultImpl;
import org.hibernate.type.descriptor.java.JavaType;
@ -67,19 +68,21 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
private static final FetchOptions FETCH_OPTIONS = FetchOptions.valueOf( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
private final Map<String, ModelPart> modelParts;
private final Map<String, ModelPart> modelPartMap;
private final ModelPart[] modelParts;
private final DomainType<?> domainType;
private final String componentName;
private final EmbeddableValuedModelPart existingModelPartContainer;
private final int fetchableIndex;
public AnonymousTupleEmbeddableValuedModelPart(
Map<String, ModelPart> modelParts,
Map<String, ModelPart> modelPartMap,
DomainType<?> domainType,
String componentName,
EmbeddableValuedModelPart existingModelPartContainer,
int fetchableIndex) {
this.modelParts = modelParts;
this.modelPartMap = modelPartMap;
this.modelParts = modelPartMap.values().toArray( new ModelPart[0] );
this.domainType = domainType;
this.componentName = componentName;
this.existingModelPartContainer = existingModelPartContainer;
@ -88,12 +91,21 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
@Override
public ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
return modelParts.get( name );
return modelPartMap.get( name );
}
@Override
public void forEachSubPart(IndexedConsumer<ModelPart> consumer, EntityMappingType treatTarget) {
for ( int i = 0; i < modelParts.length; i++ ) {
consumer.accept( i, modelParts[i] );
}
}
@Override
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
modelParts.values().forEach( consumer );
for ( int i = 0; i < modelParts.length; i++ ) {
consumer.accept( modelParts[i] );
}
}
@Override
@ -148,7 +160,7 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
@Override
public int getNumberOfAttributeMappings() {
return modelParts.size();
return modelParts.length;
}
@Override
@ -166,6 +178,17 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
throw new UnsupportedOperationException();
}
@Override
public <X, Y> int decompose(
Object domainValue,
int offset,
X x,
Y y,
JdbcValueBiConsumer<X, Y> valueConsumer,
SharedSessionContractImplementor session) {
throw new UnsupportedOperationException();
}
@Override
public Object[] getValues(Object instance) {
return existingModelPartContainer.getEmbeddableTypeDescriptor()
@ -192,6 +215,11 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
.setValue( instance, value );
}
@Override
public int getSelectableIndex(String selectableName) {
throw new UnsupportedOperationException();
}
@Override
public SelectableMapping getSelectable(int columnIndex) {
final List<SelectableMapping> results = new ArrayList<>();
@ -199,6 +227,16 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
return results.get( columnIndex );
}
@Override
public Fetchable getFetchable(int position) {
return (Fetchable) modelParts[position];
}
@Override
public JdbcMapping getJdbcMapping(int index) {
return getSelectable( index ).getJdbcMapping();
}
@Override
public List<JdbcMapping> getJdbcMappings() {
final List<JdbcMapping> results = new ArrayList<>();
@ -214,12 +252,22 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
@Override
public int forEachSelectable(int offset, SelectableConsumer consumer) {
int span = 0;
for ( ModelPart mapping : modelParts.values() ) {
for ( ModelPart mapping : modelParts ) {
span += mapping.forEachSelectable( offset + span, consumer );
}
return span;
}
@Override
public void forEachInsertable(int offset, SelectableConsumer consumer) {
throw new UnsupportedOperationException();
}
@Override
public void forEachUpdatable(int offset, SelectableConsumer consumer) {
throw new UnsupportedOperationException();
}
@Override
public String getContainingTableExpression() {
return "";
@ -234,7 +282,7 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
final List<ColumnReference> columnReferences = CollectionHelper.arrayList( getJdbcTypeCount() );
final NavigablePath navigablePath = tableGroup.getNavigablePath().append( componentName );
final TableReference tableReference = tableGroup.resolveTableReference( navigablePath, getContainingTableExpression() );
for ( ModelPart modelPart : modelParts.values() ) {
for ( ModelPart modelPart : modelParts ) {
modelPart.forEachSelectable(
(columnIndex, selection) -> {
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver()
@ -339,7 +387,7 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
@Override
public int getNumberOfFetchables() {
return modelParts.size();
return modelParts.length;
}
@Override
@ -376,7 +424,7 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
NavigablePath navigablePath,
TableGroup tableGroup,
DomainResultCreationState creationState) {
for ( ModelPart mapping : modelParts.values() ) {
for ( ModelPart mapping : modelParts ) {
mapping.applySqlSelections( navigablePath, tableGroup, creationState );
}
}
@ -387,7 +435,7 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
TableGroup tableGroup,
DomainResultCreationState creationState,
BiConsumer<SqlSelection, JdbcMapping> selectionConsumer) {
for ( ModelPart mapping : modelParts.values() ) {
for ( ModelPart mapping : modelParts ) {
mapping.applySqlSelections( navigablePath, tableGroup, creationState, selectionConsumer );
}
}
@ -400,27 +448,33 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
Y y,
JdbcValueBiConsumer<X, Y> valueConsumer,
SharedSessionContractImplementor session) {
final Object[] values = (Object[]) domainValue;
assert values.length == modelParts.size();
int span = 0;
int i = 0;
for ( ModelPart mapping : modelParts.values() ) {
final Object attributeValue = values[ i ];
span += mapping.breakDownJdbcValues( attributeValue, offset + span, x, y, valueConsumer, session );
i++;
if ( domainValue == null ) {
for ( ModelPart mapping : modelParts ) {
span += mapping.breakDownJdbcValues( null, offset + span, x, y, valueConsumer, session );
}
}
else {
final Object[] values = (Object[]) domainValue;
assert values.length == modelParts.length;
for ( int i = 0; i < modelParts.length; i++ ) {
final Object attributeValue = values[i];
span += modelParts[i].breakDownJdbcValues( attributeValue, offset + span, x, y, valueConsumer, session );
}
}
return span;
}
@Override
public Object disassemble(Object value, SharedSessionContractImplementor session) {
if ( value == null ) {
return null;
}
final Object[] values = (Object[]) value;
final Object[] result = new Object[ modelParts.size() ];
int i = 0;
for ( ModelPart mapping : modelParts.values() ) {
final Object[] result = new Object[ modelParts.length ];
for ( int i = 0; i < modelParts.length; i++ ) {
Object o = values[i];
result[i] = mapping.disassemble( o, session );
i++;
result[i] = modelParts[i].disassemble( o, session );
}
return result;
@ -428,11 +482,18 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
@Override
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
final Object[] values = (Object[]) value;
int i = 0;
for ( ModelPart mapping : modelParts.values() ) {
mapping.addToCacheKey( cacheKey, values[i], session );
i++;
if ( value == null ) {
for ( ModelPart mapping : modelParts ) {
mapping.addToCacheKey( cacheKey, null, session );
}
}
else {
final Object[] values = (Object[]) value;
int i = 0;
for ( ModelPart mapping : modelParts ) {
mapping.addToCacheKey( cacheKey, values[i], session );
i++;
}
}
}
@ -444,12 +505,17 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
Y y,
JdbcValuesBiConsumer<X, Y> valuesConsumer,
SharedSessionContractImplementor session) {
final Object[] values = (Object[]) value;
int span = 0;
int i = 0;
for ( ModelPart mapping : modelParts.values() ) {
span += mapping.forEachDisassembledJdbcValue( values[i], span + offset, x, y, valuesConsumer, session );
i++;
if ( value == null ) {
for ( ModelPart mapping : modelParts ) {
span += mapping.forEachDisassembledJdbcValue( null, span + offset, x, y, valuesConsumer, session );
}
}
else {
final Object[] values = (Object[]) value;
for ( int i = 0; i < modelParts.length; i++ ) {
span += modelParts[i].forEachDisassembledJdbcValue( values[i], span + offset, x, y, valuesConsumer, session );
}
}
return span;
}
@ -462,13 +528,18 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
Y y,
JdbcValuesBiConsumer<X, Y> consumer,
SharedSessionContractImplementor session) {
final Object[] values = (Object[]) value;
int span = 0;
int i = 0;
for ( ModelPart attributeMapping : modelParts.values() ) {
final Object o = values[i];
span += attributeMapping.forEachJdbcValue( o, span + offset, x, y, consumer, session );
i++;
if ( value == null ) {
for ( ModelPart mapping : modelParts ) {
span += mapping.forEachJdbcValue( null, span + offset, x, y, consumer, session );
}
}
else {
final Object[] values = (Object[]) value;
for ( int i = 0; i < modelParts.length; i++ ) {
final Object o = values[i];
span += modelParts[i].forEachJdbcValue( o, span + offset, x, y, consumer, session );
}
}
return span;
}
@ -476,7 +547,7 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
@Override
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
int span = 0;
for ( ModelPart attributeMapping : modelParts.values() ) {
for ( ModelPart attributeMapping : modelParts ) {
span += attributeMapping.forEachJdbcType( span + offset, action );
}
return span;