Skip to content

Commit

Permalink
[#1299] Fix issues with remove view by id when element type of cascad…
Browse files Browse the repository at this point in the history
…ed collection uses embedded id
  • Loading branch information
beikov committed Apr 23, 2021
1 parent 1006d3b commit e1fac65
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ None yet
* Fix issues with de-serializing of singular entity view attributes that use a collection type
* Add Cockroach DBMS detection and a `DbmsDialect` implementation
* Fix various issues with type resolving paths that match entity names
* Fix issues with remove view by id when element type of cascaded collection uses embedded id

### Backwards-incompatible changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1372,19 +1372,17 @@ private static CollectionRemoveListener createOrphanRemoveListener(AbstractMetho
if (!attribute.isOrphanRemoval()) {
return null;
}

if (elementDescriptor.isSubview()) {
return new ViewCollectionRemoveListener(elementDescriptor.getLoadOnlyViewToEntityMapper());
} else {
return EntityCollectionRemoveListener.INSTANCE;
}
return createCollectionRemoveListener(elementDescriptor);
}

private static CollectionRemoveListener createCascadeDeleteListener(AbstractMethodAttribute<?, ?> attribute, TypeDescriptor elementDescriptor) {
if (!attribute.isDeleteCascaded()) {
return null;
}
return createCollectionRemoveListener(elementDescriptor);
}

private static CollectionRemoveListener createCollectionRemoveListener(TypeDescriptor elementDescriptor) {
if (elementDescriptor.isSubview()) {
return new ViewCollectionRemoveListener(elementDescriptor.getLoadOnlyViewToEntityMapper());
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.blazebit.persistence.parser.util.JpaMetamodelUtils;
import com.blazebit.persistence.spi.ExtendedAttribute;
import com.blazebit.persistence.spi.ExtendedManagedType;
import com.blazebit.persistence.view.EntityViewSetting;
import com.blazebit.persistence.view.OptimisticLockException;
import com.blazebit.persistence.view.impl.EntityViewManagerImpl;
import com.blazebit.persistence.view.impl.accessor.Accessors;
Expand All @@ -46,6 +47,7 @@
import com.blazebit.persistence.view.impl.update.EntityViewUpdaterImpl;
import com.blazebit.persistence.view.impl.update.UpdateContext;
import com.blazebit.persistence.view.metamodel.ManagedViewType;
import com.blazebit.persistence.view.metamodel.MethodAttribute;
import com.blazebit.persistence.view.metamodel.PluralAttribute;
import com.blazebit.persistence.view.metamodel.SingularAttribute;
import com.blazebit.persistence.view.metamodel.Type;
Expand Down Expand Up @@ -73,6 +75,7 @@ public final class InverseFlusher<E> {
private final String attributeName;
private final String parentIdAttributeName;
private final String childIdAttributeName;
private final Class<?> childIdViewClass;
private final UnmappedAttributeCascadeDeleter deleter;
// Maps the parent view object to an entity via means of em.getReference
private final ViewToEntityMapper parentReferenceViewToEntityMapper;
Expand All @@ -93,14 +96,15 @@ public final class InverseFlusher<E> {
private final Mapper<E, Object> parentEntityOnChildEntityMapper;
private final InverseEntityToEntityMapper childEntityToEntityMapper;

public InverseFlusher(Class<?> parentEntityClass, String attributeName, String parentIdAttributeName, String childIdAttributeName, UnmappedAttributeCascadeDeleter deleter,
public InverseFlusher(Class<?> parentEntityClass, String attributeName, String parentIdAttributeName, String childIdAttributeName, Class<?> childIdViewClass, UnmappedAttributeCascadeDeleter deleter,
ViewToEntityMapper parentReferenceViewToEntityMapper, DirtyAttributeFlusher<?, E, Object> parentReferenceAttributeFlusher,
Mapper<E, Object> parentEntityOnChildViewMapper, TargetViewClassBasedInverseViewToEntityMapper childViewToEntityMapper, ViewToEntityMapper childReferenceViewToEntityMapper,
Mapper<E, Object> parentEntityOnChildEntityMapper, InverseEntityToEntityMapper childEntityToEntityMapper) {
this.parentEntityClass = parentEntityClass;
this.attributeName = attributeName;
this.parentIdAttributeName = parentIdAttributeName;
this.childIdAttributeName = childIdAttributeName;
this.childIdViewClass = childIdViewClass;
this.deleter = deleter;
this.parentReferenceViewToEntityMapper = parentReferenceViewToEntityMapper;
this.parentReferenceAttributeFlusher = parentReferenceAttributeFlusher;
Expand Down Expand Up @@ -283,6 +287,7 @@ public static <E> InverseFlusher<E> forAttribute(EntityViewManagerImpl evm, Map<
UnmappedAttributeCascadeDeleter deleter = null;
String parentIdAttributeName = null;
String childIdAttributeName = null;
Class<?> childIdViewClass = null;
// Only construct when orphanRemoval or delete cascading is enabled, orphanRemoval implies delete cascading
if (attribute.isDeleteCascaded()) {
EntityMetamodel entityMetamodel = evm.getMetamodel().getEntityMetamodel();
Expand All @@ -298,6 +303,13 @@ public static <E> InverseFlusher<E> forAttribute(EntityViewManagerImpl evm, Map<
} else {
ExtendedAttribute extendedAttribute = elementManagedType.getAttribute(mapping);
if (childTypeDescriptor.isSubview()) {
if (elementType instanceof ViewType<?>) {
MethodAttribute<?, ?> idAttribute = ((ViewType<?>) elementType).getIdAttribute();
if (idAttribute.isSubview()) {
// in this case, we need to fetch the id as view as the deleter expects it this way
childIdViewClass = idAttribute.getJavaType();
}
}
deleter = new ViewTypeCascadeDeleter(childTypeDescriptor.getViewToEntityMapper());
} else if (childTypeDescriptor.isJpaEntity()) {
deleter = new UnmappedBasicAttributeCascadeDeleter(evm, mapping, extendedAttribute, mapping + "." + parentIdAttributeName, false);
Expand Down Expand Up @@ -343,6 +355,7 @@ public static <E> InverseFlusher<E> forAttribute(EntityViewManagerImpl evm, Map<
attribute.getMapping(),
parentIdAttributeName,
childIdAttributeName,
childIdViewClass,
deleter,
parentReferenceViewToEntityMapper,
parentReferenceAttributeFlusher,
Expand Down Expand Up @@ -383,11 +396,15 @@ public void removeByOwnerIdOnly(UpdateContext context, Object ownerId) {

public List<PostFlushDeleter> removeByOwnerId(UpdateContext context, Object ownerId) {
EntityViewManagerImpl evm = context.getEntityViewManager();
List<Object> elementIds = (List<Object>) evm.getCriteriaBuilderFactory().create(context.getEntityManager(), parentEntityClass, "e")
.where(parentIdAttributeName).eq(ownerId)
.where("e." + attributeName + "." + childIdAttributeName).isNotNull()
.select("e." + attributeName + "." + childIdAttributeName)
.getResultList();
CriteriaBuilder<Object> cb = (CriteriaBuilder<Object>) evm.getCriteriaBuilderFactory().create(context.getEntityManager(), parentEntityClass, "e")
.where(parentIdAttributeName).eq(ownerId)
.where("e." + attributeName + "." + childIdAttributeName).isNotNull();
if (childIdViewClass == null) {
cb.select("e." + attributeName + "." + childIdAttributeName);
} else {
evm.applySetting(EntityViewSetting.create(childIdViewClass), cb, "e." + attributeName + "." + childIdAttributeName);
}
List<Object> elementIds = cb.getResultList();
if (!elementIds.isEmpty()) {
// We must always delete this, otherwise we might get a constraint violation because of the cascading delete
removeByOwnerIdOnly(context, ownerId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public ViewCollectionRemoveListener(ViewToEntityMapper viewToEntityMapper) {

@Override
public void onEntityCollectionRemove(UpdateContext context, Object element) {
viewToEntityMapper.removeById(context, viewToEntityMapper.getEntityIdAccessor().getValue(element));
Object viewId = ((CompositeAttributeFlusher) viewToEntityMapper.getFullGraphNode()).createViewIdByEntityId(viewToEntityMapper.getEntityIdAccessor().getValue(element));
viewToEntityMapper.removeById(context, viewId);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,29 @@ public void testRemoveReadOnlyElementFromCollection() {
Assert.assertEquals(0, legacyOrder.getPositions().size());
}

// Test for https://github.com/Blazebit/blaze-persistence/issues/1299
@Test
public void testRemoveById() {
// Given
UpdatableLegacyOrderView newOrder = evm.create(UpdatableLegacyOrderView.class);
UpdatableLegacyOrderPositionView position = evm.create(UpdatableLegacyOrderPositionView.class);
position.getId().setPositionId(0);
position.setArticleNumber("123");
newOrder.getPositions().add(position);
update(newOrder);

// When
em.clear();
evm.remove(em, UpdatableLegacyOrderView.class, newOrder.getId());
em.flush();
em.clear();

// Then
LegacyOrder legacyOrder = em.find(LegacyOrder.class, newOrder.getId());
Assert.assertNull(legacyOrder);

}

@Test
public void testAddElementCreateViewToCollection() {
// Given
Expand Down

0 comments on commit e1fac65

Please sign in to comment.