Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA single table inheritance with abstract generics and collection

I have classes with JPA mappings as follows:

@Entity
@Inheritance
public abstract class FieldValue<T> {
   @Id @GeneratedValue
   private Long id;

   public abstract T getValue();
}

@Entity
public class TextFieldValue extends FieldValue<String> {
   @Column(name = "TEXT_VALUE")
   private String value;

   public String getValue() { return value; }
}

@Entity
public class NumberFieldValue extends FieldValue<Double> {
   @Column(name = "NUMBER_VALUE")
   private Double value;

   public Double getValue() { return value; }
}

@Entity
public class SelectFieldValue extends FieldValue<ValueOption> {
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "SELECT_VALUE")
   private ValueOption value;

   public ValueOption getValue() { return value; }
}

I'm using a single table inheritance type, which causes each value field to map to a different column. In SelectFieldValue the value is a reference to another entity, but the mapping still works properly, populating the SELECT_VALUE column with a ValueOption's id.

However, I'd also like to add the class with a list of entities:

@Entity
public class MultipleSelectFieldValue extends FieldValue<List<ValueOption>>{
   @ManyToMany // ??
   private List<ValueOption> value;

   public List<ValueOption> getValue() { return value; }
}

I can't seem to find the proper mapping to handle such list of entities. Is this even possible with the single table inheritance strategy? It could for example populate the column for MultipleSelectFieldValue with an id of a single row in the join table, which would store many-to-many mappings from MultipleSelectFieldValue to ValueOption.

I tried the following mapping:

@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "field_value_value_option",
        joinColumns = @JoinColumn(name = "field_value_id"),
        inverseJoinColumns = @JoinColumn(name = "value_option_id"))
private List<ValueOption> value;

But strangely, it does not add a new column to the FieldValue table, hence does not work properly.

like image 775
zenn1337 Avatar asked Nov 26 '25 17:11

zenn1337


1 Answers

But strangely, it does not add a new column to the FieldValue table, hence does not work properly.

I think it works as it should.

Column is not added because there is no need for a new column. The join table does the thing. I have a bit different entity names but take a look at this data

  id  |      dtype       | number_value | string_value 
------+------------------+--------------+--------------
 1551 | StringValue      |              | hi!
 1552 | NumberValue      |           55 | 
 1553 | MultiStringValue |              |
 1554 | StringValue      |              | s1
 1555 | StringValue      |              | s2
 1556 | MultiStringValue |              | 

Then take a look on the mapping table

 field_value_id | value_option_id 
----------------+-----------------
           1553 |            1554
           1553 |            1555
           1556 |            1554
           1556 |            1555

Comparing ids you can see that Value refers to itself through mapping table. So both MultiStringValues has a relationship to two same StringValues so ManyToMany is working without new columns.

like image 59
pirho Avatar answered Nov 28 '25 05:11

pirho



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!