为何JPA API的Path.get(Map/PluralAttribute)参数无"? super X"?
Path.get(SingularAttribute) use ? super X while plural/map variants don't? Great question—this is a nuanced design decision in the JPA API that boils down to balancing flexibility for inherited single-valued attributes and type safety for collection/map attributes. Let's break this down step by step:
1. SingularAttribute: Inheritance flexibility with ? super X
Single-valued attributes (like a String name or User creator on an entity) are straightforward to inherit. Suppose you have:
- A parent class
SuperEntitywith aSingularAttribute<SuperEntity, String> NAME - A child class
ChildEntityextendingSuperEntity
When working with a Path<ChildEntity> (representing a ChildEntity instance in a query), you should be able to access the inherited NAME attribute from SuperEntity. The ? super X generic constraint allows exactly this: it accepts any SingularAttribute declared on X or any of its parent classes, since ChildEntity is a subtype of SuperEntity, and SingularAttribute<SuperEntity, String> matches SingularAttribute<? super ChildEntity, String>.
This aligns with OOP principles—subclasses inherit all parent attributes, so the API should let you query them without forcing you to cast or duplicate attribute metadata for subclasses.
2. PluralAttribute & MapAttribute: Prioritizing type safety over broad inheritance
Collection and map attributes introduce more complexity because their type is tied closely to the entity class that declares them. Here's why the API avoids ? super X here:
- Collection type specificity: A parent class might declare a
PluralAttribute<SuperEntity, Collection<Address>, Address> ADDRESSES, but a child classChildEntitycould override this to use aList<Address>instead. If the API allowed? super X, callingpath.get(ADDRESSES)on aPath<ChildEntity>would return anExpression<Collection<Address>>, but the actual runtime type isList<Address>. This creates a mismatch between the declared type and the actual type, potentially leading to unchecked casts or unexpected behavior. - Metadata binding: Plural attributes in JPA are strongly bound to the entity class that declares them. Even if a subclass inherits a collection attribute, the metadata for that attribute is still associated with the parent class. Allowing
? super Xwould blur this boundary, making it harder to ensure that the query's expression type matches the actual attribute type in the subclass. - Limited gain from flexibility: Unlike single-valued attributes, where accessing parent attributes is a common use case, collection attributes are often customized in subclasses (e.g., changing the collection implementation or cascade rules). Requiring the use of the subclass's own
PluralAttribute(even if it inherits from the parent) ensures that the query uses the correct metadata for the subclass's specific collection type.
In short, the JPA team chose to use ? super X for singular attributes to enable intuitive access to inherited properties, while avoiding it for plural/map attributes to maintain strict type safety and clear binding between attributes and their declaring entities.
内容的提问来源于stack exchange,提问作者Archie

