After a lot of experimentation, I found something that works for me.
Basically, rather than try to override the OneToMany mapping in the abstract entity class with the OneToMany mappings in the concrete entities, I had to make them completely separate mappings to completely different properties. Which means my concrete entities have two different collections of AbstractCreditDebitLineItemEntity, and some AbstractCreditDebitLineItemEntity objects will appear twice, in both collections. A bit wasteful in terms of memory/computation, but I’m okay with that, it works!
So here’s what I ended up with:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractCreditDebitEntity {
/* literally all my properties and ID and column mappings here
...
*/
private List<AbstractCreditDebitLineItemEntity> creditDebitLineItems;
@OneToMany(fetch = FetchType.LAZY, targetEntity = AbstractCreditDebitLineItemEntity.class)
@JoinColumn(
name = "MyIdColumnName",
referencedColumnName = "MyIdColumnName",
updatable = false,
insertable = false
)
public List<AbstractCreditDebitLineItemEntity> getCreditDebitLineItems() {
return creditDebitLineItems;
}
public void setCreditDebitLineItems(List<AbstractCreditDebitLineItemEntity> items) {
creditDebitLineItems = items;
}
}
@Entity
@Table(name = "tblCredits")
public final class Credit extends AbstractCreditDebitEntity {
private List<CreditLineItem> creditLineItems;
@OneToMany(cascade = CascadeType.ALL, targetEntity = CreditLineItem.class)
@LazyCollection(LazyCollectionOption.FALSE)
@JoinColumn(
name = "MyIdColumnName",
referencedColumnName = "MyIdColumnName"
)
public List<CreditLineItem> getCreditLineItems() {
return creditLineItems;
}
@Override
public void setCreditDebitLineItems(List<CreditLineItem> items) {
creditLineItems = items;
}
}
With the exact same pattern repeated for the Debit entity.
This allows me to both:
-
persist, using the OneToMany mappings from the concrete Credit and Debit entities to the concrete CreditLineItem and DebitLineItem entities; and
-
do finds on the Spring Data JPA repository of AbstractCreditDebitEntity, using the the completely separate OneToMany mapping from that abstract entity to the AbstractCreditDebitLineItemEntity.
Not as clean as if I’d been able to override the OneToMany mapping in the abstract parent class with a more specific OneToMany mapping in the concrete child classes… but as I said, it works!
(The answer on this issue helped me know I needed to replace fetchType=FetchType.EAGER
on my concrete OneToMany mappings with @LazyCollection(LazyCollectionOption.FALSE)
:
java - Hibernate throws MultipleBagFetchException - cannot simultaneously fetch multiple bags - Stack Overflow)