You say,
And what I'm trying to achieve is to query different tables for retrieving both Car and Bus entities.
, but as a first consideration, you should evaluate whether you really want to do that. Think about this:
The single-table inheritance strategy is generally the fastest for whole-hierarchy queries such as you imagine performing. It can perform both whole-hierarchy and concrete-entity operations with single queries, without joins or unions.
The single-table and joined inheritance strategies ensure that all entities in the hierarchy have distinct keys, which is not necessarily the case for the table-per-class strategy.
The single-table and joined inheritance strategies facilitate relationships involving the abstract superclass; these are not well supported by the table-per-class strategy.
Support for the table-per-class strategy is optional. JPA providers are not required to support it, and the default provider in the GlassFish reference implementation in fact does not support it. Applications that rely on table-per-class therefore are not guaranteed to be portable. (Your provider, Hibernate, does support it.)
You go on to say,
However, in this case I get java.sql.SQLSyntaxErrorException:
ORA-00904: "KEY": invalid identifier
. Seems like using @Inheritance
together with @AttributeOverride
for @Id
field doesn't work.
@AttributeOverride
is only specified to work for overriding the attributes of mapped superclasses and fields and properties of embedded classes. It does work for @Id
properties if they appear in those contexts. It is not specified to work (though neither is it specified to not work) for persistent fields and properties inherited from an entity superclass, but do observe that it cannot work for such properties with either the single-table or the joined inheritance strategy.
If @AttributeOverride
did happen to work for you, that use would be non-portable. On the other hand, JPA has nothing else to accomplish what you want. A particular persistence provider could have an extension that supports it, but Hibernate has not historically done so -- all properties inherited from an entity superclass are mapped with the same names.
You also say,
One more thing I'd like to mention is that I've tried using
@MappedSuperclass
instead of @Inheritance
but in this case I'm not
able to query with abstact Vehicle
type.
JPA does not provide a solution for your particular combination of requirements:
- Mapping each concrete entity class to a separate table,
- Naming the ID to a different column name in each entity table, and
- Supporting polymorphic queries on the abstract supertype.
If you are unwilling to change any of those then you'll have to rely on an extension. And in that case you're in luck: Hibernate supports polymorphic queries where the polymorphic type is not mapped as an entity. Thus, if you're willing to make your application explicitly dependent on Hibernate, you can probably get where you want to be.
Specifically, to do this in Hibernate you would rely on "implicit polymorphism". To do this, you would avoid mapping the superclass as an entity, and from your experience, I guess it should not be a mapped superclass, either. It can be an ordinary class, though its properties would not be persistent, or you could use an interface instead. If your Vehicle
class has properties that you want to make persistent, then you could change it to an embeddable class. You would furthermore annotate each of the vehicle entities to specify implicit polymorphism, for example:
@Entity
@Polymorphism(type = PolymorphismType.IMPLICIT)
// ...
public class Car implements Vehicle {
// ...
}
The Hibernate docs claim that implicit polymorphism is the default, but I recommend applying the @Polymorphism
annotation anyway, for clarity.