Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PostgreSQL inheritance with JPA, Hibernate

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 (
    idAnswer SERIAL,
    answerContent VARCHAR,
    idQuestion INTEGER,
    version INTEGER,

    CONSTRAINT Answer_idAnswer_PK PRIMARY KEY (idAnswer),
    CONSTRAINT Answer_idQuestion_FK FOREIGN KEY (idQuestion) REFERENCES Question(idQuestion)
);


CREATE TABLE MatchAnswer (
    matchingAnswer VARCHAR NOT NULL,
    version INTEGER,

    CONSTRAINT MatchAnswer_idAnswer_PK PRIMARY KEY (idAnswer)       
) INHERITS(Answer);


CREATE TABLE TrueFalseAnswer (
    isTrue BOOLEAN NOT NULL,
    version INTEGER,

    CONSTRAINT TrueFalseAnswer_idAnswer_PK PRIMARY KEY (idAnswer)   
) INHERITS(Answer);

And we mapped them for entities using automatic tool in Netbeans 7.1.2. At first I thought it would be enough just to add

@Entity
@Table(name = "truefalseanswer", catalog = "jobfairdb", schema = "public")
@XmlRootElement
public class Truefalseanswer extends Answer implements Serializable {
    private static final 

so just extends, but it didn't work properly. What is the best approach to this? Thanks in advance.

like image 908
Atais Avatar asked Aug 07 '12 08:08

Atais


People also ask

Can I use Hibernate with PostgreSQL?

Out of the box, Hibernate works pretty well with PostgreSQL databases.

What inheritance strategies does JPA offer?

There are three inheritance strategies defined from the InheritanceType enum, SINGLE_TABLE , TABLE_PER_CLASS and JOINED . Single table inheritance is the default, and table per class is an optional feature of the JPA spec, so not all providers may support it.

Does Postgres support inheritance?

In PostgreSQL, a table can inherit from zero or more other tables. Here the ONLY before cities indicates that the query should be run over only the cities table, and not tables below cities in the inheritance hierarchy.

Which inheritance strategy is better in Hibernate?

Single Table. The single table strategy maps all entities of the inheritance structure to the same database table. This approach makes polymorphic queries very efficient and provides the best performance.


1 Answers

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.

like image 53
Craig Ringer Avatar answered Sep 29 '22 15:09

Craig Ringer