Edwin Bautista
Edwin Bautista

Reputation: 364

JPA Discriminator SINGLE_TABLE inheritance

I have a HeaderTable with three child tables Sub1, Sub2 and Sub3. Sub1 and Sub2 needs to refer to the same row data in HeaderTable, while Sub3 needs to refer to another row data.

What I did was create an abstractHeader which is then extended by two implementation of header, HeaderTableA and HeaderTableB.

HeaderTableA has a list of Sub1 and Sub2 while HeaderTableB has list of Sub3.

The discriminator column in the HeaderTable is messageType which is then set to discriminator value "WO" on HeaderTableA and "CO" on HeaderTableB.

There is no problem persisting HeaderTableB(CASCADE.ALL to Sub3) because it contains only one list. The problem occurs when I try persisting HeaderTableA where both list of sub1 and list sub2 has data. But if only list of sub1 or list of sub2 is populated, then it also persist without problem.

The error encountered insist that the foreign key ID(headerID) does not exist.

Something like this:

@Entity
@Table(name="CODE")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType=DiscriminatorType.STRING, name="codeType")
@DiscriminatorValue(value="UNKNOWN")
public abstract class BusinessCode extends DateExpirableWithId<Long> {

    private static final long serialVersionUID = -2766041951015641149L;

    private String code;

    @Column(updatable=false, insertable=false)
    private String codeType;

    private String language;

    private String description;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getCodeType() {
        return codeType;
    }

    public void setCodeType(String codeType) {
        this.codeType = codeType;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("BusinessCode [code=");
        builder.append(code);
        builder.append(", codeType=");
        builder.append(codeType);
        builder.append(", language=");
        builder.append(language);
        builder.append(", description=");
        builder.append(description);
        builder.append("]");
        return builder.toString();
    }
}


@Entity
@DiscriminatorValue(value="CountryCode")
public class CountryCode extends BusinessCode {

    private static final long serialVersionUID = -7207238725104662784L;

    private List<SubProperty1> subProperties1;
    private List<SubProperty2> subProperties2;

    public List<SubProperty1> getSubProperties1() {
        return subProperties1;
    }

    public void setSubProperties1(List<SubProperty1> subProperties1) {
        this.subProperties1 = subProperties1;
    }

    public List<SubProperty2> getSubProperties2() {
        return subProperties2;
    }

    public void setSubProperties2(List<SubProperty2> subProperties2) {
        this.subProperties2 = subProperties2;
    }
}

Please refer to the diagram below for better description of the table structure: enter image description here

Upvotes: 3

Views: 4183

Answers (1)

Strelok
Strelok

Reputation: 51481

I think that sounds more like InheritanceType.JOINED. You don't need discriminators for JOINED strategy.

BusinessCode.java (assuming here that your super class has the ID column etc.)

@Entity
@Table(name="CODE")
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class BusinessCode extends DateExpirableWithId<Long> {

    private static final long serialVersionUID = -2766041951015641149L;

    @Column(nullable = false)
    private String code;

    @Column(nullable = false)
    private String language;

    @Column(nullable = false)
    private String description;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

CountryCode.java

@Entity
@Table(name="COUNTRY_CODE")
@Inheritance(strategy = InheritanceType.JOINED)
public class CountryCode extends BusinessCode {
  @Column
  private String countryName;

  public String getCountryName() { return countryName; }
  public String setCountryName(String value) { countryName = value; }
}

DepartmentCode.java

@Entity
@Table(name="DEPARTMENT_CODE")
@Inheritance(strategy = InheritanceType.JOINED)
public class DepartmentCode extends BusinessCode {
  @Column
  private String departmentName;

  public String getDepartmentName() { return departmentName; }
  public String setDepartmentName(String value) { departmentName= value; }
}

Your table structure will look something like this:

BUSINESS_CODE
  ID(PK)
  CODE,
  LANGUAGE,
  DESCRIPTION

COUNTRY_CODE
  ID(FK), 
  COUNTRYNAME

DEPARTMENT_CODE
  ID(FK)
  DEPARTMENTNAME

And data will look something like this:

BUSINESS_CODE
1, "AU","EN","australia country code in english"
2, "AU","FR","australia country code in french"
3, "FIN","EN","finance department code"

COUNTRY_CODE
1, "Australia"
2, "Australie"

DEPARTMENT_CODE
3, "Bean Counters"

Upvotes: 2

Related Questions