Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheritance with Java and Hibernate - Typecasting on updates

I have the following hierarchy in my classes

@Entity
@Table(name = "Parent")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Parent {
}

@Entity
@DiscriminatorVlaue("FirstChild")
public class FirstChild extends Parent {
}

@Entity
@DiscriminatorVlaue("SecondChild")
public class SecondChild extends Parent {
}

This creates a table Parent as expected.

Some business logic in my app:

As the request is accepted , it is persisted as "Parent" type and creates the following entry in the table

Dtype    id  value
Parent   1   "some value"

As the request is processed it could either be of type FirstChild or of type SecondChild so in my code somewhere I have

if (some condition is met) {
// change the Parent to its firstChild type
}
else {
// chnage it to "SecondChild" type
}

Is my understanding and usage of inheritance correct? I am essentially downcasting objects in the if loop which throw runtime exceptions, but does changing the type of an object also change the DTYPE value in the database? I am essentially using inheritance to keep things organized as their types. Is there some magic I can do in the constructors to achieve this? But the real question is is the Dtype modifiable on an update?

To work with this further,

I created contsructors in the child classes as

public FirstChild(Parent parent) {
id = parent.id
}

but this creates a new row for the sub types ,

  Dtype       id  value
  Parent      1   "some value"
  FirstChild  2   "some value"

I am making sure that the "firstChild" record is created with the parent ID (1) but I am not sure why a second row is created

like image 423
user_mda Avatar asked Mar 29 '19 15:03

user_mda


2 Answers

There is not a real inheritance in relational databases. Hibernate is just simulating it. Inheritance is a programming concept to use other classes like an owner. But you can't use other table as owning table.. In an child table if you have an element than you have a parent but where is the parent ? Parent is an element too.. ( a row of data ). So you simulate it in databases. Hibernate has some inheritance strategies.'SINGLE_TABLE' is one of them and collects parent table and child tables in 1 table. To differantiate which type is which class uses 'DiscriminatorColumn' on database. This column cant be changed it is static and declared with your java class. You can use 'DiscriminatorValue' to select a value to identify a java class at 'DiscriminatorColumn'. So your inheritance understanding is differs on relational databases. You must declare every child row data on parent table rows...

like image 104
Burak Akyıldız Avatar answered Sep 28 '22 12:09

Burak Akyıldız


But the real question is is the Dtype modifiable on an update?

No, you cant: source.

From your example your pure java code would look like this:

Parent parent = new Parent(); //object received from request, stored in database as it is
if (some conditions is met) {
   // FirstChild firstChild = (Parent) parent; //this would throw ClassCastException
   FirstChild firstChild = new FirstChild(parent); //creating new object, gc will collect parent
}

So hibernate act same way as java: you cannot update Parent, you have to create new record for firstChild and delete parent.

Wouldn't be helpfull for you use @DiscriminatorFormula instead of checking some condition is met when processing the request?

@DiscriminatorFormula("case when value = 'some value' then 'FirstChild' else 'SecondChild' end")

Then you wouldnt have to save Parent and then process its records.

like image 27
Tijkijiki Avatar answered Sep 28 '22 12:09

Tijkijiki