How to access discriminator column in JPA
Asked Answered
R

3

11

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?

Ryun answered 23/4, 2017 at 11:59 Comment(2)
Why you need same column for both?Forensics
@PeterŠály I don't. But would like to know if I was.Ryun
T
31

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.

Tallbott answered 23/4, 2017 at 17:5 Comment(4)
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?Jacqulynjactation
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.Tallbott
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)Settle
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.Sensor
P
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.

Peccable answered 23/4, 2017 at 13:52 Comment(2)
So, just remove discriminator annotation?Ryun
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.Ryun
W
0

Or use for example:

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

This is far simple the using @DiscriminatorColumn...

Wanettawanfried answered 24/5, 2021 at 12:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.