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(){
...
}
}
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?