use of com.blazebit.persistence.view.metamodel.MappingAttribute in project blaze-persistence by Blazebit.
the class Mappers method forViewConvertToViewAttributeMapping.
public static <S, T> Mapper<S, T> forViewConvertToViewAttributeMapping(EntityViewManagerImpl evm, ViewType<S> sourceViewType, ViewType<T> targetViewType, Map<String, String> mapping, Mapper<S, T> additionalMapper) {
List<Mapper<S, T>> mappers = new ArrayList<>();
ExpressionFactory ef = evm.getCriteriaBuilderFactory().getService(ExpressionFactory.class);
for (MethodAttribute<?, ?> attribute : targetViewType.getAttributes()) {
if (attribute.isUpdatable() && attribute instanceof MappingAttribute<?, ?> && attribute instanceof SingularAttribute<?, ?>) {
for (Map.Entry<String, String> entry : mapping.entrySet()) {
if (entry.getValue().equals(((MappingAttribute) attribute).getMapping())) {
Type<?> attributeType = ((SingularAttribute<?, ?>) attribute).getType();
AttributeAccessor entityAccessor;
if (entry.getKey().isEmpty()) {
entityAccessor = Accessors.forEntityMapping(evm, sourceViewType.getEntityClass(), ((MappingAttribute<?, ?>) sourceViewType.getIdAttribute()).getMapping());
} else {
entityAccessor = Accessors.forEntityMapping(evm, sourceViewType.getEntityClass(), entry.getKey());
}
AttributeAccessor targetAttributeAccessor = Accessors.forMutableViewAttribute(evm, attribute);
if (attributeType instanceof ViewType<?>) {
ViewType<?> viewType = (ViewType<?>) attributeType;
Type<?> attributeViewIdType = ((SingularAttribute<?, ?>) viewType.getIdAttribute()).getType();
EntityTupleizer entityTupleizer = null;
ObjectBuilder<?> idViewBuilder = null;
if (attributeViewIdType instanceof ManagedViewType<?>) {
entityTupleizer = new DefaultEntityTupleizer(evm, (ManagedViewType<?>) attributeViewIdType);
idViewBuilder = (ObjectBuilder<Object>) evm.getTemplate(new MacroConfigurationExpressionFactory(ef, ef.getDefaultMacroConfiguration()), (ManagedViewTypeImplementor<?>) attributeViewIdType, null, null, new MutableViewJpqlMacro(), null, new MutableEmbeddingViewJpqlMacro(), 0).createObjectBuilder(null, null, null, 0, false, false);
}
mappers.add(new ReferenceViewAttributeMapper<S, T>(evm, entityAccessor, viewType.getJavaType(), entityTupleizer, targetAttributeAccessor, idViewBuilder));
} else {
mappers.add((Mapper<S, T>) new AttributeMapper<>(Collections.singletonList(entityAccessor), Collections.singletonList(targetAttributeAccessor)));
}
}
}
}
}
if (mappers.isEmpty()) {
return additionalMapper;
}
return new CompositeMapper<>(mappers.toArray(new Mapper[mappers.size()]));
}
use of com.blazebit.persistence.view.metamodel.MappingAttribute in project blaze-persistence by Blazebit.
the class ViewMetamodelTest method testNoMappingNonConflictingMapping.
@Test
public void testNoMappingNonConflictingMapping() {
ViewMetamodel metamodel = build(NoMappingNonConflictingDoc.class).getMetamodel();
MappingAttribute<?, ?> mappingAttribute = (MappingAttribute<?, ?>) metamodel.view(NoMappingNonConflictingDoc.class).getAttribute("name");
assertEquals("COALESCE(name, '')", mappingAttribute.getMapping());
}
use of com.blazebit.persistence.view.metamodel.MappingAttribute in project blaze-persistence by Blazebit.
the class ViewMetamodelTest method testResolveConflictingMapping.
@Test
public void testResolveConflictingMapping() {
EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration();
cfg.addEntityView(ResolveConflictingDoc.class);
ViewMetamodel metamodel = build(ResolveConflictingDoc.class).getMetamodel();
MappingAttribute<?, ?> mappingAttribute = (MappingAttribute<?, ?>) metamodel.view(ResolveConflictingDoc.class).getAttribute("name");
assertEquals("UPPER(name)", mappingAttribute.getMapping());
}
use of com.blazebit.persistence.view.metamodel.MappingAttribute in project blaze-persistence by Blazebit.
the class EntityViewUpdaterImpl method createPluralAttributeSubFlusher.
private DirtyAttributeFlusher<?, ?, ?> createPluralAttributeSubFlusher(EntityViewManagerImpl evm, Map<Object, EntityViewUpdaterImpl> localCache, ManagedViewTypeImplementor<?> viewType, AbstractMethodAttribute<?, ?> attribute, String name, Type<?> type, EntityViewUpdaterImpl owner, String ownerMapping) {
EntityMetamodel entityMetamodel = evm.getMetamodel().getEntityMetamodel();
String attributeName = attribute.getName() + "_" + name;
String attributeMapping = attribute.getMapping();
String attributeLocation = attribute.getLocation();
Set<Type<?>> readOnlyAllowedSubtypes = attribute.getReadOnlyAllowedSubtypes();
Set<Type<?>> persistAllowedSubtypes = attribute.getPersistCascadeAllowedSubtypes();
Set<Type<?>> updateAllowedSubtypes = attribute.getUpdateCascadeAllowedSubtypes();
if (type instanceof ManagedViewType<?>) {
ManagedViewTypeImplementor<?> subviewType = (ManagedViewTypeImplementor<?>) type;
if (!(subviewType.getJpaManagedType() instanceof EntityType<?>)) {
// A singular attribute where the subview refers to an embeddable type
EmbeddableUpdaterBasedViewToEntityMapper viewToEntityMapper = new EmbeddableUpdaterBasedViewToEntityMapper(attributeLocation, evm, subviewType.getJavaType(), readOnlyAllowedSubtypes, persistAllowedSubtypes, updateAllowedSubtypes, EntityLoaders.referenceLoaderForAttribute(evm, localCache, subviewType, attribute), false, null, owner, ownerMapping == null ? attributeMapping : ownerMapping + "." + attributeMapping, localCache);
String parameterName = attributeName + "_";
String updateFragment = attributeMapping + ".";
return new EmbeddableAttributeFlusher<>(attributeName, attributeMapping, updateFragment, parameterName, false, false, false, null, null, viewToEntityMapper);
} else {
ViewTypeImplementor<?> attributeViewType = (ViewTypeImplementor<?>) subviewType;
InitialValueAttributeAccessor viewAttributeAccessor = Accessors.forMutableViewAttribute(evm, attribute);
AttributeAccessor subviewIdAccessor;
ManagedType<?> ownerManagedType = owner == null ? viewType.getJpaManagedType() : owner.managedViewType.getJpaManagedType();
EntityType<?> ownerEntityType = ownerManagedType instanceof EntityType<?> ? (EntityType<?>) ownerManagedType : null;
String attributeElementIdMapping;
if (ownerEntityType != null && attribute.getMapping() != null) {
ExtendedManagedType<?> extendedManagedType = evm.getMetamodel().getEntityMetamodel().getManagedType(ExtendedManagedType.class, attributeViewType.getEntityClass());
attributeElementIdMapping = TypeDescriptor.getAttributeElementIdentifier(evm, ownerEntityType, attribute.getName(), ownerMapping, attribute.getMapping(), extendedManagedType.getType());
} else {
attributeElementIdMapping = ((MappingAttribute<?, ?>) attributeViewType.getIdAttribute()).getMapping();
}
subviewIdAccessor = Accessors.forSubviewAssociationId(evm, attributeViewType, attributeElementIdMapping, true);
Attribute<?, ?> attributeIdAttribute = attributeViewType.getJpaManagedType().getAttribute(attributeElementIdMapping);
javax.persistence.metamodel.Type<?> attributeIdAttributeType = entityMetamodel.type(JpaMetamodelUtils.resolveFieldClass(attributeViewType.getEntityClass(), attributeIdAttribute));
List<String> idComponentMappings;
boolean requiresComponentWiseSetInUpdate = true;
if (requiresComponentWiseSetInUpdate && attributeIdAttributeType instanceof EmbeddableType<?>) {
// If the identifier used for the association is an embeddable, we must collect the individual attribute components since updates don't work on embeddables directly
Set<Attribute<?, ?>> idAttributeComponents = (Set<Attribute<?, ?>>) ((EmbeddableType<?>) attributeIdAttributeType).getAttributes();
idComponentMappings = new ArrayList<>(idAttributeComponents.size());
for (Attribute<?, ?> idAttributeComponent : idAttributeComponents) {
idComponentMappings.add(attributeMapping + "." + attributeElementIdMapping + "." + idAttributeComponent);
}
} else {
idComponentMappings = Collections.singletonList(attributeMapping + "." + attributeElementIdMapping);
}
String[] idAttributeMappings = idComponentMappings.toArray(new String[idComponentMappings.size()]);
ViewToEntityMapper viewToEntityMapper = createViewToEntityMapper(attributeLocation, evm, localCache, ownerEntityType, attributeName, attributeMapping, attributeViewType, false, false, readOnlyAllowedSubtypes, persistAllowedSubtypes, updateAllowedSubtypes, EntityLoaders.referenceLoaderForAttribute(evm, localCache, attributeViewType, attribute.getViewTypes(), attributeElementIdMapping), owner, ownerMapping);
String parameterName = attributeName;
return new SubviewAttributeFlusher<>(attributeName, attributeMapping, false, true, false, false, false, subviewType.getConverter(), false, idAttributeMappings, parameterName, false, owner != null, null, viewAttributeAccessor, subviewIdAccessor, viewToEntityMapper, null, null);
}
} else {
TypeDescriptor elementDescriptor = TypeDescriptor.forType(evm, localCache, this, attribute, type, owner, ownerMapping);
String parameterName = attributeName;
String updateFragment = attributeMapping;
// TODO: Why?
boolean supportsQueryFlush = !elementDescriptor.isJpaEmbeddable();
return new BasicAttributeFlusher<>(attributeName, attributeMapping, supportsQueryFlush, false, true, false, false, false, null, elementDescriptor, updateFragment, parameterName, null, null, null, null, null);
}
}
use of com.blazebit.persistence.view.metamodel.MappingAttribute in project blaze-persistence by Blazebit.
the class ViewTypeObjectBuilderTemplate method applyMapping.
@SuppressWarnings("unchecked")
private void applyMapping(AbstractAttribute<?, ?> attribute, String parentAttributePath, TupleElementMapperBuilder mapperBuilder, Set<Feature> features, TupleIdDescriptor tupleIdDescriptor, ViewJpqlMacro viewJpqlMacro, EmbeddingViewJpqlMacro embeddingViewJpqlMacro, ExpressionFactory ef) {
String attributePath = getAttributePath(parentAttributePath, attribute, false);
int batchSize = attribute.getBatchSize();
if (batchSize == -1) {
batchSize = attribute.getDeclaringType().getDefaultBatchSize();
}
if (attribute.isSubquery()) {
applySubqueryMapping((SubqueryAttribute<? super T, ?>) attribute, attributePath, mapperBuilder, embeddingViewJpqlMacro);
} else {
if (attribute.isCollection()) {
PluralAttribute<? super T, ?, ?> pluralAttribute = (PluralAttribute<? super T, ?, ?>) attribute;
TypeConverter<Object, Object> keyConverter = null;
TypeConverter<Object, Object> valueConverter = (TypeConverter<Object, Object>) pluralAttribute.getElementType().getConverter();
boolean listKey = pluralAttribute.isIndexed() && pluralAttribute instanceof ListAttribute<?, ?>;
boolean mapKey = pluralAttribute.isIndexed() && pluralAttribute instanceof MapAttribute<?, ?, ?>;
int startIndex = tupleOffset + mapperBuilder.mapperIndex();
int valueStartIndex = startIndex + 1;
if (pluralAttribute.getFetchStrategy() == FetchStrategy.JOIN) {
if (listKey) {
MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
features.add(Feature.INDEXED_COLLECTIONS);
applyIndexCollectionFunctionMapping(IntegerBasicUserType.INSTANCE, mappingAttribute, attributePath, mapperBuilder, embeddingViewJpqlMacro);
} else if (mapKey) {
MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
features.add(Feature.INDEXED_COLLECTIONS);
MapAttribute<?, ?, ?> mapAttribute = (MapAttribute<?, ?, ?>) pluralAttribute;
keyConverter = (TypeConverter<Object, Object>) mapAttribute.getKeyType().getConverter();
if (mapAttribute.isKeySubview()) {
features.add(Feature.SUBVIEWS);
ManagedViewTypeImpl<Object[]> managedViewType = (ManagedViewTypeImpl<Object[]>) mapAttribute.getKeyType();
applySubviewMapping(mappingAttribute, attributePath, tupleIdDescriptor, managedViewType, mapperBuilder, viewJpqlMacro, embeddingViewJpqlMacro, ef, true, true);
valueStartIndex = tupleOffset + mapperBuilder.mapperIndex();
} else {
applyIndexCollectionFunctionMapping(TypeUtils.forType(mapAttribute.getKeyType()), mappingAttribute, attributePath, mapperBuilder, embeddingViewJpqlMacro);
}
}
}
boolean dirtyTracking = pluralAttribute instanceof MethodAttribute<?, ?> && attribute.needsDirtyTracker();
if (pluralAttribute.isSubview()) {
features.add(Feature.SUBVIEWS);
TupleIdDescriptor newTupleIdDescriptor;
if ((listKey || mapKey) && pluralAttribute.getFetchStrategy() == FetchStrategy.JOIN && !pluralAttribute.isCorrelated()) {
newTupleIdDescriptor = new TupleIdDescriptor(tupleIdDescriptor);
newTupleIdDescriptor.addIdPosition(startIndex);
} else {
newTupleIdDescriptor = tupleIdDescriptor;
}
if (pluralAttribute.isCorrelated() || (pluralAttribute.getFetchStrategy() != FetchStrategy.JOIN || attribute.getLimitExpression() != null) && pluralAttribute.getFetchStrategy() != FetchStrategy.MULTISET) {
ManagedViewTypeImplementor<Object> managedViewType = (ManagedViewTypeImplementor<Object>) pluralAttribute.getElementType();
if (attribute.getFetchStrategy() == FetchStrategy.MULTISET) {
boolean updatableObjectCache = managedViewType.isUpdatable() || managedViewType.isCreatable();
boolean nullIfEmpty = managedViewType instanceof ViewType<?>;
ViewTypeObjectBuilderTemplate<Object[]>[] templates = applyCorrelatedSubviewMapping(attribute, attributePath, tupleIdDescriptor, (ManagedViewTypeImplementor<Object[]>) (ManagedViewTypeImplementor<?>) managedViewType, mapperBuilder, features, viewJpqlMacro, embeddingViewJpqlMacro, ef, batchSize, false);
ViewTypeObjectBuilderTemplate<Object[]> subviewTemplate = templates[0];
ViewTypeObjectBuilderTemplate<Object[]> indexTemplate = templates[1];
SubviewTupleTransformerFactory indexTransformerFactory = null;
BasicUserTypeStringSupport<?> indexBasicTypeSupport = null;
if (indexTemplate != null) {
boolean updatableKeyObjectCache = indexTemplate.viewType.isUpdatable() || indexTemplate.viewType.isCreatable();
indexTransformerFactory = new SubviewTupleTransformerFactory(attributePath, indexTemplate, updatableKeyObjectCache, true);
} else if (mapKey) {
indexBasicTypeSupport = TypeUtils.forType(((MapAttribute<?, ?, ?>) attribute).getKeyType());
} else if (listKey) {
indexBasicTypeSupport = IntegerBasicUserType.INSTANCE;
}
mapperBuilder.addTupleTransformerFactory(new CollectionMultisetTupleTransformerFactory(startIndex, null, attributePath, getMultisetResultAlias(attributePath), valueConverter, attribute.getContainerAccumulator(), dirtyTracking, subviewTemplate, indexTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty), indexTransformerFactory, null, indexBasicTypeSupport));
} else {
applyCorrelatedSubviewMapping(attribute, attributePath, newTupleIdDescriptor, (ManagedViewTypeImplementor<Object[]>) (ManagedViewTypeImplementor<?>) managedViewType, mapperBuilder, features, viewJpqlMacro, embeddingViewJpqlMacro, ef, batchSize, dirtyTracking);
}
} else {
MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
ManagedViewTypeImplementor<Object[]> managedViewType = (ManagedViewTypeImplementor<Object[]>) pluralAttribute.getElementType();
boolean nullIfEmpty = managedViewType instanceof ViewType<?> || !listKey && !mapKey;
if (pluralAttribute.getFetchStrategy() == FetchStrategy.MULTISET) {
boolean updatableObjectCache = managedViewType.isUpdatable() || managedViewType.isCreatable();
String mapping = mapperBuilder.getMapping(mappingAttribute);
ViewTypeObjectBuilderTemplate<Object[]>[] templates = applySubviewMapping(mappingAttribute, attributePath, newTupleIdDescriptor, managedViewType, mapperBuilder, viewJpqlMacro, embeddingViewJpqlMacro, ef, false, nullIfEmpty);
ViewTypeObjectBuilderTemplate<Object[]> subviewTemplate = templates[0];
ViewTypeObjectBuilderTemplate<Object[]> indexTemplate = templates[1];
SubviewTupleTransformerFactory indexTransformerFactory = null;
BasicUserTypeStringSupport<?> indexBasicTypeSupport = null;
if (indexTemplate != null) {
boolean updatableKeyObjectCache = indexTemplate.viewType.isUpdatable() || indexTemplate.viewType.isCreatable();
indexTransformerFactory = new SubviewTupleTransformerFactory(attributePath, indexTemplate, updatableKeyObjectCache, true);
} else if (mapKey) {
indexBasicTypeSupport = TypeUtils.forType(((MapAttribute<?, ?, ?>) attribute).getKeyType());
} else if (listKey) {
indexBasicTypeSupport = IntegerBasicUserType.INSTANCE;
}
mapperBuilder.addTupleTransformerFactory(new CollectionMultisetTupleTransformerFactory(startIndex, mapping, attributePath, getMultisetResultAlias(attributePath), valueConverter, attribute.getContainerAccumulator(), dirtyTracking, subviewTemplate, indexTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty), indexTransformerFactory, null, indexBasicTypeSupport));
} else {
// Obviously, we produce null if the object type is identifiable i.e. a ViewType and it is empty = null id
// Additionally, we also consider empty embeddables as null when we have a non-indexed collection so we can filter out these elements
applySubviewMapping(mappingAttribute, attributePath, newTupleIdDescriptor, managedViewType, mapperBuilder, viewJpqlMacro, embeddingViewJpqlMacro, ef, false, nullIfEmpty);
}
}
} else if (mapKey) {
MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
applyCollectionFunctionMapping(TypeUtils.forType(getType(mappingAttribute)), mappingAttribute, attributePath, mapperBuilder, mappingAttribute.getFetches(), embeddingViewJpqlMacro);
} else {
// TODO: Multiset basic fetching?
if (pluralAttribute.isCorrelated() || attribute.getFetchStrategy() == FetchStrategy.JOIN && !attribute.getOrderByItems().isEmpty() || pluralAttribute.getFetchStrategy() != FetchStrategy.JOIN && pluralAttribute.getFetchStrategy() != FetchStrategy.MULTISET) {
applyBasicCorrelatedMapping(attribute, attributePath, mapperBuilder, features, ef, batchSize, dirtyTracking, embeddingViewJpqlMacro);
} else {
MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
applyBasicMapping(mappingAttribute, attributePath, mapperBuilder, embeddingViewJpqlMacro);
}
}
if (pluralAttribute.getFetchStrategy() == FetchStrategy.JOIN) {
if (listKey) {
if (pluralAttribute.isSorted()) {
throw new IllegalArgumentException("The list attribute '" + pluralAttribute + "' can not be sorted!");
} else {
mapperBuilder.addTupleListTransformer(new IndexedTupleListTransformer(tupleIdDescriptor.createIdPositions(), startIndex, valueStartIndex, attribute.getContainerAccumulator(), dirtyTracking, null, valueConverter));
}
} else if (mapKey) {
mapperBuilder.addTupleListTransformer(new IndexedTupleListTransformer(tupleIdDescriptor.createIdPositions(), startIndex, valueStartIndex, attribute.getContainerAccumulator(), dirtyTracking, keyConverter, valueConverter));
} else {
switch(pluralAttribute.getCollectionType()) {
case COLLECTION:
if (pluralAttribute.isSorted()) {
throw new IllegalArgumentException("The collection attribute '" + pluralAttribute + "' can not be sorted!");
}
break;
case LIST:
if (pluralAttribute.isSorted()) {
throw new IllegalArgumentException("The list attribute '" + pluralAttribute + "' can not be sorted!");
}
break;
case SET:
break;
case MAP:
throw new IllegalArgumentException("Ignoring the index on the attribute '" + pluralAttribute + "' is not possible!");
default:
throw new IllegalArgumentException("Unknown collection type: " + pluralAttribute.getCollectionType());
}
mapperBuilder.addTupleListTransformer(new NonIndexedTupleListTransformer(tupleIdDescriptor.createIdPositions(), startIndex, attribute.getCollectionInstantiator(), dirtyTracking, valueConverter));
}
}
} else if (attribute.isQueryParameter()) {
MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
features.add(Feature.PARAMETERS);
applyQueryParameterMapping(mappingAttribute, mapperBuilder);
} else if (attribute.isSubview()) {
features.add(Feature.SUBVIEWS);
boolean nullIfEmpty = !((SingularAttribute<?, ?>) attribute).isCreateEmptyFlatView();
if (attribute.isCorrelated() || attribute.getFetchStrategy() == FetchStrategy.JOIN && !attribute.getOrderByItems().isEmpty() || attribute.getFetchStrategy() != FetchStrategy.JOIN && attribute.getFetchStrategy() != FetchStrategy.MULTISET) {
ManagedViewTypeImplementor<Object> managedViewType = (ManagedViewTypeImplementor<Object>) ((SingularAttribute<?, ?>) attribute).getType();
if (attribute.getFetchStrategy() == FetchStrategy.MULTISET) {
int startIndex = tupleOffset + mapperBuilder.mapperIndex();
boolean updatableObjectCache = managedViewType.isUpdatable() || managedViewType.isCreatable();
ViewTypeObjectBuilderTemplate<Object[]> subviewTemplate = applyCorrelatedSubviewMapping(attribute, attributePath, tupleIdDescriptor, (ManagedViewTypeImplementor<Object[]>) (ManagedViewTypeImplementor<?>) managedViewType, mapperBuilder, features, viewJpqlMacro, embeddingViewJpqlMacro, ef, batchSize, false)[0];
TypeConverter<Object, Object> elementConverter = (TypeConverter<Object, Object>) (TypeConverter<?, ?>) managedViewType.getConverter();
mapperBuilder.addTupleTransformerFactory(new SingularMultisetTupleTransformerFactory(startIndex, null, attributePath, getMultisetResultAlias(attributePath), elementConverter, subviewTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty)));
} else {
applyCorrelatedSubviewMapping(attribute, attributePath, tupleIdDescriptor, (ManagedViewTypeImplementor<Object[]>) (ManagedViewTypeImplementor<?>) managedViewType, mapperBuilder, features, viewJpqlMacro, embeddingViewJpqlMacro, ef, batchSize, false);
}
} else {
MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
ManagedViewTypeImplementor<Object[]> managedViewType = (ManagedViewTypeImplementor<Object[]>) ((SingularAttribute<?, ?>) attribute).getType();
if (attribute.getFetchStrategy() == FetchStrategy.MULTISET) {
int startIndex = tupleOffset + mapperBuilder.mapperIndex();
boolean updatableObjectCache = managedViewType.isUpdatable() || managedViewType.isCreatable();
String mapping = mapperBuilder.getMapping(mappingAttribute);
ViewTypeObjectBuilderTemplate<Object[]> subviewTemplate = applySubviewMapping(mappingAttribute, attributePath, tupleIdDescriptor, managedViewType, mapperBuilder, viewJpqlMacro, embeddingViewJpqlMacro, ef, false, nullIfEmpty)[0];
TypeConverter<Object, Object> elementConverter = (TypeConverter<Object, Object>) (TypeConverter<?, ?>) managedViewType.getConverter();
mapperBuilder.addTupleTransformerFactory(new SingularMultisetTupleTransformerFactory(startIndex, mapping, attributePath, getMultisetResultAlias(attributePath), elementConverter, subviewTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty)));
} else {
applySubviewMapping(mappingAttribute, attributePath, tupleIdDescriptor, managedViewType, mapperBuilder, viewJpqlMacro, embeddingViewJpqlMacro, ef, false, nullIfEmpty);
}
}
} else {
if (attribute.isCorrelated() || attribute.getFetchStrategy() == FetchStrategy.JOIN && !attribute.getOrderByItems().isEmpty() || attribute.getFetchStrategy() != FetchStrategy.JOIN && attribute.getFetchStrategy() != FetchStrategy.MULTISET) {
applyBasicCorrelatedMapping(attribute, attributePath, mapperBuilder, features, ef, batchSize, false, embeddingViewJpqlMacro);
} else {
MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
applyBasicMapping(mappingAttribute, attributePath, mapperBuilder, embeddingViewJpqlMacro);
}
}
}
}
Aggregations