Cannot use identity column key generation with <union-subclass> ( TABLE_PER_CLASS )

HibernateInheritanceJpaClass Table-Inheritance

Hibernate Problem Overview


com.something.SuperClass:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class SuperClass implements Serializable {
    private static final long serialVersionUID = -695503064509648117L;
    
    long confirmationCode;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO) // Causes exception!!!
    public long getConfirmationCode() {
        return confirmationCode;
    }

    public void setConfirmationCode(long confirmationCode) {
        this.confirmationCode = confirmationCode;
    }
}

com.something.SubClass:

@Entity
public abstract class Subclass extends SuperClass {
    private static final long serialVersionUID = 8623159397061057722L;

    String name;

    @Column(nullable = false)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Gives me this exception:

Caused by: org.hibernate.MappingException: Cannot use identity column key
generation with <union-subclass> mapping for: com.something.SuperClass

What's the best and most convenient way for me to generate the ID's? I do not want to change my inheritance strategy.

Hibernate Solutions


Solution 1 - Hibernate

The problem here is that you mix "table-per-class" inheritance and GenerationType.Auto. Consider an identity column in MsSQL. It is column based. In a "table-per-class" strategy you use one table per class and each one has an ID.

Try:

@GeneratedValue(strategy = GenerationType.TABLE)

Solution 2 - Hibernate

I wonder if this is a database dialect specific problem, since watching a youtube tutorial with PostgreSQL as the underlying database I saw that the creator of the video run succefully an app with the default @GeneratedValue. In my case (the underlying database is MySQL) I had to modify the @GeneratedValue strategy to GenerationType.TABLE exactly as zoidbeck proposes.

Here is the video : https://www.youtube.com/watch?v=qIdM4KQOtH8

Solution 3 - Hibernate

Agree with zoidbeck's answer. You need to change strategy to:

@GeneratedValue(strategy = GenerationType.TABLE)

But that's not all, you need to create a new table, what will hold your abstract's table primary key sequence. Modify your mapping to

@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "ConfirmationCodeGenerator")
@TableGenerator(table = "SEQUENCES", name = "ConfirmationCodeGenerator")
public long getConfirmationCode() {
   return confirmationCode;
}

And a new table in database should look like following: enter image description here

When you ran your application, Hibernate will insert a row where sequence_name will be the entity name (SuperClass in this example) and sequence_next_hi_value value will be automatically incremented and used for new records of all implementing subclasses's tables.

Solution 4 - Hibernate

In our case, we use a PostreSQL database for dev and production and an in-memory hsqldb database for tests. We are using a sequence in both cases to generate an id. Apparently GenerationType.AUTO defaults to SEQUENCE for postgres, but failed in our local tests (must default to something else for hsqldb).

So the solution that worked for us, explicitly use GenerationType.SEQUENCE.

Solution 5 - Hibernate

you can use @MappedSuperclass for inheritance

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser14070View Question on Stackoverflow
Solution 1 - HibernatezoidbeckView Answer on Stackoverflow
Solution 2 - HibernateskiaboxView Answer on Stackoverflow
Solution 3 - HibernateGondyView Answer on Stackoverflow
Solution 4 - HibernateRyan WallsView Answer on Stackoverflow
Solution 5 - HibernateleimbagView Answer on Stackoverflow