Search code examples
hibernatejpagenericspolymorphism

Hibernate/JPA polymorphie and generic type


I try to combine polymorphie and generic types in hibernate/JPA entities. Here are the example entities:

public class Cake {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Size(max = 36)
    @Column(length = 36)
    @UserInterface(showInForm = false, showInList = false)
    @Comment("Primary key")
    private String id;

    @Version
    @NotNull
    @UserInterface(showInForm = false, showInList = false)
    @Comment("Version column for optimistic locking")
    private int version;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }
}
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Ingredient {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Size(max = 36)
    @Column(length = 36)
    @UserInterface(showInForm = false, showInList = false)
    @Comment("Primary key")
    private String id;

    @Version
    @NotNull
    @UserInterface(showInForm = false, showInList = false)
    @Comment("Version column for optimistic locking")
    private int version;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }
}
@Entity
public class Vegetable extends Ingredient {
}
@Entity
public class Fruit extends Ingredient {
}
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class CakeIngredientLink<T extends Ingredient> {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Size(max = 36)
    @Column(length = 36)
    @UserInterface(showInForm = false, showInList = false)
    @Comment("Primary key")
    private String id;

    @Version
    @NotNull
    @UserInterface(showInForm = false, showInList = false)
    @Comment("Version column for optimistic locking")
    private int version;

    @ManyToOne(optional = false)
    private Cake cake;

    @ManyToOne(optional = false)
    private T ingredient;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    public Cake getCake() {
        return cake;
    }

    public void setCake(Cake cake) {
        this.cake = cake;
    }

    public T getIngredient() {
        return ingredient;
    }

    public void setIngredient(T ingredient) {
        this.ingredient = ingredient;
    }
}
@Entity
public class CakeVegetable extends CakeIngredientLink<Vegetable> {
}
@Entity
public class CakeFruit extends CakeIngredientLink<Fruit> {
}

With @MappedSuperclass this design is possible. But with @Inheritance(strategy = InheritanceType.JOINED) I get following exception:

Property de.cakeproject.domain.CakeIngredientLink.ingredient has an unbound type and no explicit target entity. Resolve this Generic usage issue or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type

I want to use polymorphic queries to get all ingredients for a cake. This is not possible with @MappedSuperclass. What is a good way to achieve this problem?


Solution

  • I have learned, and also tested, that it is possible to query a mappedSuperclass. The only thing you need to know is that the FQN of the entity is required in the query.

    Hibernate can also query interfaces or base classes that are not entities but are extended or implemented by entity classes.

    Baeldung

    I'm not sure if this is specific to hibernate, but it's fine for me as a hibernate user.