10

I have DisseminationArea as subcalss for Feature with the following code:

@Entity
@Table(name = "features")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "subtype_id", discriminatorType = DiscriminatorType.INTEGER)
public class Feature {

   @Id
   @Column(name="id")
   @GeneratedValue(generator="sqlite")
   @TableGenerator(name="sqlite", table="sqlite_sequence",
      pkColumnName="name", valueColumnName="seq",
      pkColumnValue="features")
   @Getter
   @Setter
   private long id;

   @ManyToOne
   @JoinColumn(name = "subtype_id")
   @Getter
   @Setter
   private FeatureSubtype featureSubtype;

   @ManyToOne
   @JoinColumn(name = "parent_id")
   @Getter
   @Setter
   private Feature parent;

   ...    
}

Unfortunately, this causes an exception when save this entity to database, because subtype_id field is used twice.

Can I annotate it somehow so that JPA know it is the same field?

Dims
  • 47,675
  • 117
  • 331
  • 600

3 Answers3

29

If a discriminator column makes sense with InheritanceType.JOINED is worth discussing. I would tend to omit it on joined strategy and only use it with InheritanceType.SINGLE_TABLE.

Nevertheless, it's possible to map it without duplicate column errors.

If your superclass entity has an inheritance / discriminator definition like:

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "subtype_id", discriminatorType = DiscriminatorType.INTEGER)

You just have to adjust the mapping to not update the value as usual by setting it readonly:

@Column(name="subtype_id", insertable = false, updatable = false)
protected int subTypeId;

public int getSubTypeId() {
    return subTypeId;
}

Now you can access the discriminator value of the entity.

Kevin Peters
  • 3,314
  • 1
  • 17
  • 38
  • Different inherited class have different constraints and when inserting new values it creates an issue. For eg: Class A needs String X as nonnull while Class B dont have String x. While interting values in class B error is thrown. Do you think in this Case Joined should not be used? – Raj Shah Oct 07 '18 at 00:58
  • I would say JOINED makes sense if you need different tables for each class, but then you don't need a discriminator column. Either a common table with discriminator (because it's needed to distinguish the types) or each type gets it's own table. – Kevin Peters Oct 10 '18 at 13:47
  • 1
    Heads up that as of the time I am posting this, if one adds a `@DisctiminatorColumn(...` and also tries to incorrectly expose the column with a simple `@Column` annotation (missing insertable, and updatable), JDK 11's stack trace incorrectly advises :`(should be mapped with insert="false" update="false)` – Edwin Diaz Sep 11 '19 at 23:17
  • 1
    I have a single-table inheritance, one abstract super class and two subclasses. Need to search on the discriminator column, so I have to have setter/getter of the discriminator column. After I added "insertable = false, updatable = false", the code was deployed to server without error. – Janet Jan 20 '21 at 01:46
0

Same column name is used for relation FK to FeatureSubtype. Use other name for discriminator or don't use discriminator at all.

In Hibernate, discriminator column on joined inheritance is supported but not required. Hibernate is querying all subtables to determine correct subclass.

Peter Šály
  • 2,848
  • 2
  • 12
  • 26
  • So, just remove discriminator annotation? – Dims Apr 23 '17 at 14:33
  • 1
    Sorry, I removed the field. Also, I need to set discriminator column type, and the only way to do this is by this annotation. Will accept your answer when ready. – Dims Apr 25 '17 at 10:11
0

Or use for example:

th:text="${OBJECTNAME.class.getSimpleName()}"

This is far simple the using @DiscriminatorColumn...

Aymen
  • 1,476
  • 18
  • 28