I have to create a hierarchy of classes where a superclass has a @CollectionTable
representing a map. I tried to implement it but it works only with one child class.
I want to do the following. I have the current structure on the left, and the desired structure on the right.
The stable (working) code looks like this:
@MappedSuperclass
public class Animal {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Long id;
}
@Entity(name = "cats")
@Audited
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.CHAR)
@DiscriminatorValue(value = Cat.PET_TYPE)
public abstract class Cat extends Animal {
public static final String PET_TYPE = "C";
@ElementCollection(fetch = FetchType.EAGER)
@MapKeyColumn(name = "name")
@Column(name = "value")
@CollectionTable(name = "cat_properties", joinColumns = @JoinColumn(name = "cat_id"))
private Map<String, String> properties = new HashMap<>();
}
@Audited
@Entity(name = "persiancats")
@DiscriminatorValue(value = PersianCat.PERSIAN_CAT_TYPE)
public class PersianCat extends Cat {
public static final String PERSIAN_CAT_TYPE = "P";
}
This is how I tried to achieve the modification:
@MappedSuperclass
public class Animal {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Long id;
}
@MappedSuperclass
public abstract class Pet extends Animal {
@ElementCollection(fetch = FetchType.EAGER)
@MapKeyColumn(name = "name")
@Column(name = "value")
@CollectionTable(name = "pet_properties", joinColumns = @JoinColumn(name = "pet_id"))
private Map<String, String> properties = new HashMap<>();
}
@Entity(name = "cats")
@Audited
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.CHAR)
@DiscriminatorValue(value = Cat.PET_TYPE)
public class Cat extends Pet {
public static final String PET_TYPE = "C";
}
@Entity(name = "dogs")
@Audited
public class Dog extends Pet {
}
@Audited
@Entity(name = "persiancats")
@DiscriminatorValue(value = PersianCat.PERSIAN_CAT_TYPE)
public class PersianCat extends Pet {
public static final String PERSIAN_CAT_TYPE = "P";
}
Hibernate creates the pet_properties
table but it only references either dogs
or cats
. My intention was to create a common table for both dog and cat (and persiancat) properties.
What am I missing or doing wrong?
I guess what you're trying to achieve is logically impossible, and here's why (I stumbled upon the same problem, although in another domain). To reference a table from your pet_properties
table Hibernate creates a foreign key from pet_properties
to the target table (dogs or cats in your case). A foreign key essentially means to every entry in this table should correspond an entry from another table, and that another table is only one table. Therefore, if you said that your pet_properties
entry references both dogs
and cats
tables, then it will immediately break the foreign key properties, because if it references dogs, then it doesn't reference cats, and vice versa.
So the auto-generated option that Hibernate gave you (separate tables dogs_properties
and cats_properties
) seems to be the correct way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With