PostgreSQL inheritance with JPA, Hibernate

后端 未结 3 2075
一整个雨季
一整个雨季 2020-12-19 08:36

we have question about inheritance in PostgreSQL and mapping it as entities in JPA. Our database, and tables we want to map are:

CREATE TABLE Answer (
    id         


        
相关标签:
3条回答
  • 2020-12-19 08:59

    There is a solution using MappedSuperClass annotation.

    @MappedSuperClass
    public abstract class AbstractAnswer{
        @Id
        protected Long idAnswer;
    
        @Column(name="answerContent")
        protected String answerContent;
    }
    
    @Entity
    @Table(name="Answer")
    public class Answer extends AbstractAnswer{
    
    }
    
    @Entity
    @Table(name="MatchAnswer")
    public class MatchAnswer extends AbstractAnswer{
        protected String matchingAnswer;
    }
    
    @Entity
    @Table(name="TrueFalseAnswer")
    public class TrueFalseAnswer extends AbstractAnswer{
        protected Boolean trueFalseAnswer;
    }
    
    0 讨论(0)
  • 2020-12-19 09:03

    Inheritance in Hibernate has nothing to do with PostgreSQL inheritance, even though both try to accomplish the same and might look the same.

    The reason for this is that Hibernate takes the SQL standards as base, and adjusts the small specific features from each RDBMS. For instance, while MySQL have an "auto-increment" for sequential IDs, Oracle uses sequences.

    Historically, data inheritance (or specialization) has been done by using separate tables for the specific fields, with primary-foreign-keys linking the tables together. In your example, MatchAnswer would have the ID as PK and FK to Answer.idAnswer. Same with TrueFalseAnswer (the ID is PK/FK to Answer.idAnswer).

    The "inherits" definition that you posted is not (AFAIK) defined in any SQL standard, so, I'd be surprised if Hibernate supported this, specially because it seems to be something extremely specific to PostgreSQL and it seems it's a somewhat experimental feature: look at "Caveats" on the "Inheritance" chapter of the PostgreSQL documentation.

    That said, I'd suggest to keep your data sane, mapping them according to the best relational-model practices. Then, in your Hibernate mappings, you can express data inheritance where it makes sense.

    0 讨论(0)
  • 2020-12-19 09:17

    JPA's concept of inheritance is based on ordinary tables. It doesn't really "get" the idea of PostgreSQL's table inheritance. That's one of the costs of working with a spec designed to expose the lowest common denominator of features and do so portably.

    See this guide for a decent summary of JPA inheritance strategies. Note that in the newer Java 6 JavaDoc for @Inheritance there is a note saying that:

    If the Inheritance annotation is not specified or if no inheritance type is specified for an entity class hierarchy, the SINGLE_TABLE mapping strategy is used.

    ... and if you look at how SINGLE_TABLE works, it's not surprising it doesn't work for you; it's expecting all subclasses to be in one big table with a magic discriminator value.

    InheritanceType.TABLE_PER_CLASS is closer to how Pg behaves, but I suspect that the JPA impl will get a bit confused when the base type tables have entries for each entity of a leaf type. It tries to do things like UNION queries across the subclass tables when querying on the superclass, and that could produce odd results - at least duplication if UNION is used and performance issues if it uses UNION ALL. Depending on exactly how the provider implements the strategy it may work at least partially. You'd have to test, and the results would possibly be fairly provider specific.

    A really good implementation of PG inheritance support for JPA would probably require JPA provider extensions for a new inheritance strategy that understood the PostgreSQL extensions for inheritance and for ONLY queries.

    If you can convince your JPA implementation to use SELECT ... FROM ONLY subclass_table when in InheritanceType.TABLE_PER_CLASS mode then it should inter-operate OK with PostgreSQL inheritance. It would see only the non-inherited rows in each table and work with them as if they were ordinary tables. Your other non-JPA code could then keep using the inheritance features. I guess it's possible you could modify the PostgreSQL dialect code for Hibernate to do this, but personally I wouldn't go there unless I absolutely had to make JPA support existing PostgreSQL schema that relied heavily on inheritance.

    0 讨论(0)
提交回复
热议问题