1

I inherited some pretty awful code that I am looking to refactor to make more reusable. There is a set of reporting tables which are primarily composed of 3 columns: id, report_type_fk, and report_description. I would like to merge all the reporting tables into one for ease of use.

I am refactoring the code and think that it would be better to break our current entities up so that Report is an abstract class with type implementations. For example a DmvReport extends Report, CreditScoreReport extends Report, etc.

The problem I am running into is that there would only be 1 report table that all entities would need to save to. Is there a way to make all concrete implementations of the abstract Report object save into the same table?

Here's an example of the bad code I inherited

Report class

@Entity
@Table(name = "report")
public class Report<E extends Exception> {
    private long id;
    private ReportType type;
    private String description;
   ...
   ...
}

CreditReport class

@Entity
@Table(name = "credit_report")
public class CreditScore Report<E extends Exception> extends Report<E> {
    private long id;
    private ReportType type;
    private String description;
   ...
   ...
}

I am looking to turn it into:

@MappedSuperclass
@Table(name = "report")
public abstract class Report<E extends Exception> {
    @Id @Column(name="id")
    private long id;

    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "report_type_id")
    private ReportType type;

    @column(name="description")
    private String description;
   ...
   ...
}

@Entity
@Table(name = "report")
public class CreditScoreReport<E extends Exception> extends Report<E> {

   public void doCreditScoreStuff(){
      ...
   }
}

@Entity
@Table(name = "report")
public class DmvReport<E extends Exception> extends Report<E> {
   public void doDmvStuff(){
      ...
   }
}
Dan
  • 979
  • 1
  • 8
  • 29
  • Have a look at [this](http://stackoverflow.com/questions/5257921/hibernate-how-override-an-attribute-from-mapped-super-class/5258090#5258090) which already should cover your question. – Alexander Bischof Mar 28 '17 at 00:26
  • @AlexanderBischof - I do not see any examples of multiple concrete implementations saving to the same table. – Dan Mar 28 '17 at 01:37

1 Answers1

2

I think you should use @Inheritance instead of @MappedSuperClass. Your code would look like this:

@Entity
@Table(name = "report")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "report_type_id", discriminatorType = DiscriminatorType.INTEGER)
public abstract class Report<E extends Exception> {
    @Id @Column(name="id")
    private long id;

    @column(name="description")
    private String description;
   ...
   ...
}

@Entity(name = "CreditScoreReport")
@DiscriminatorValue("1") // the id corresponding to the credit score report
public class CreditScoreReport<E extends Exception> extends Report<E> {

   @Column(name = "specific_credit_score_report_1)
   private Integer specificCreditScoreReport1;

   public void doCreditScoreStuff(){
      ...
   }
}

@Entity(name = "DmvReport")
@DiscriminatorValue("2") // the id corresponding to the DMV report
public class DmvReport<E extends Exception> extends Report<E> {

   @Column(name = "specific_dmv_score_report_1)
   private Integer specificDmvScoreReport1;

   public void doDmvStuff(){
      ...
   }
}

This strategy allows you to store credit score report and DMV report data in one table (report), but instanciate the proper entity according to the report_value_id field. You don't have to define the report_value_id in your parameters because it was already used to create the required entity.

Is this what you're looking for?

Francois
  • 586
  • 2
  • 6
  • 19