Cascade delete throws an exception about an missing id
Description
When deleting a entity of (yet unknown pattern) via cascade, we get this exception
java.lang.IllegalArgumentException: Attribute 'id' not found on type 'ModerationPageRevisionState'
Expected behavior
It should work work just like that i suppose.
Actual behavior
Exception with stacktrace
java.lang.IllegalArgumentException: Attribute 'id' not found on type 'ModerationPageRevisionState'
at com.blazebit.persistence.parser.PathTargetResolvingExpressionVisitor.visit(PathTargetResolvingExpressionVisitor.java:244)
at com.blazebit.persistence.parser.expression.PropertyExpression.accept(PropertyExpression.java:41)
at com.blazebit.persistence.parser.PathTargetResolvingExpressionVisitor.visit(PathTargetResolvingExpressionVisitor.java:337)
at com.blazebit.persistence.parser.expression.PathExpression.accept(PathExpression.java:85)
at com.blazebit.persistence.impl.JpaUtils.getAttributeForJoining(JpaUtils.java:476)
at com.blazebit.persistence.impl.JoinManager.implicitJoinSingle(JoinManager.java:3553)
at com.blazebit.persistence.impl.JoinManager.implicitJoin(JoinManager.java:2932)
at com.blazebit.persistence.impl.JoinVisitor.visit(JoinVisitor.java:268)
at com.blazebit.persistence.impl.JoinVisitor.visit(JoinVisitor.java:219)
at com.blazebit.persistence.parser.expression.PathExpression.accept(PathExpression.java:85)
at com.blazebit.persistence.impl.JoinVisitor.removeAssociationIdIfPossible(JoinVisitor.java:444)
at com.blazebit.persistence.impl.JoinVisitor.visit(JoinVisitor.java:376)
at com.blazebit.persistence.parser.predicate.EqPredicate.accept(EqPredicate.java:57)
at com.blazebit.persistence.parser.expression.VisitorAdapter.visit(VisitorAdapter.java:223)
at com.blazebit.persistence.parser.predicate.CompoundPredicate.accept(CompoundPredicate.java:77)
at com.blazebit.persistence.impl.PredicateManager.acceptVisitor(PredicateManager.java:246)
at com.blazebit.persistence.impl.AbstractCommonQueryBuilder.applyImplicitJoins(AbstractCommonQueryBuilder.java:2674)
at com.blazebit.persistence.impl.AbstractCommonQueryBuilder.prepareAndCheck(AbstractCommonQueryBuilder.java:3594)
at com.blazebit.persistence.impl.AbstractCommonQueryBuilder.getBaseQueryStringWithCheck(AbstractCommonQueryBuilder.java:2813)
at com.blazebit.persistence.impl.AbstractCommonQueryBuilder.getTypedQuery(AbstractCommonQueryBuilder.java:2828)
at com.blazebit.persistence.impl.AbstractQueryBuilder.getQuery(AbstractQueryBuilder.java:53)
at com.blazebit.persistence.impl.AbstractQueryBuilder.getResultList(AbstractQueryBuilder.java:58)
at com.blazebit.persistence.view.impl.update.flush.UnmappedBasicAttributeCascadeDeleter.removeByOwnerId(UnmappedBasicAttributeCascadeDeleter.java:133)
at com.blazebit.persistence.view.impl.update.flush.UnmappedBasicAttributeCascadeDeleter.removeByOwnerId(UnmappedBasicAttributeCascadeDeleter.java:192)
at com.blazebit.persistence.view.impl.update.flush.UnmappedCollectionAttributeCascadeDeleter.removeByOwnerId(UnmappedCollectionAttributeCascadeDeleter.java:125)
at com.blazebit.persistence.view.impl.update.flush.CompositeAttributeFlusher.remove(CompositeAttributeFlusher.java:996)
at com.blazebit.persistence.view.impl.update.flush.CompositeAttributeFlusher.remove(CompositeAttributeFlusher.java:938)
at com.blazebit.persistence.view.impl.update.EntityViewUpdaterImpl.remove(EntityViewUpdaterImpl.java:746)
at com.blazebit.persistence.view.impl.EntityViewManagerImpl.remove(EntityViewManagerImpl.java:1135)
at com.blazebit.persistence.view.impl.EntityViewManagerImpl.remove(EntityViewManagerImpl.java:1125)
Steps to reproduce
2 Entities with an OneToOne relation, while the 'childEntity` uses the PK of the parent entity as its own PK (and FK) The parent
@Data
@Entity
@Accessors(chain = true)
@ToString(of = {"id", "title", "lastModified"})
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class PageRevision implements Serializable
{
@Id
@Include
@Column(name = "vid", columnDefinition = "INT(10)")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(mappedBy = "pageRevision", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private ModerationPageRevisionState pageModerationState;
}
That is the 'child'
public class ModerationPageRevisionState implements Serializable
{
@Id
@Column(name = "vid", columnDefinition = "INT(11)")
private Long pageRevisionId;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "vid", referencedColumnName = "vid", columnDefinition = "INT(10)", insertable = false,
updatable = false)
private PageRevision pageRevision;
}
Environment
Version: 1.6.1 JPA-Provider: Hibernate 5.1.2 DBMS: mariadb:10.3
The relevant part is the following:
class Page {
@OneToMany(mappedBy = "page", cascade = ALL)
Set<PageRevision> set;
}
class PageRevision {
@ManyToOne
Page page;
@OneToOne(mappedBy = "pageRevision", cascade = ALL)
PageModerationState pageModerationState;
}
class PageModerationState {
@OneToOne
PageRevision pageRevision;
}
When running evm.remove(PageIdView.class, 1), the nested CascadeDeleter for pageModerationState lacks the mappedBy information, so the owner id path is just id instead of pageRevision.id