Reputation: 643
I am having some difficulty in understanding how inheritance works with relational databases.
Suppose I have the following classes:
public class Train {
private int id;
private String callsign;
private List<Component> components = new ArrayList<Component>();
public Train(){}
public Train(String callsign){
this.callsign = callsign;
}
... getters & setters ...
}
public abstract class Component {
private int id;
private String callsign;
private Train train;
public Component() {
}
public Component(String callsign) {
this.callsign = callsign;
}
... getters & setters ...
}
public class Wagon extends Component{
private int numOfSeats;
public Wagon(String callsign, int numOfSeats) {
super(callsign);
this.numOfSeats = numOfSeats;
}
public Wagon() {
}
... getters & setters ...
}
A Train is build up out of components (List) and there are multiple component subclasses (only Wagon in this example).
In order to persist this, I thought a Table Per Type Inheritance
structure would be appropriate but this is where I run into problems.
My database structure:
CREATE TABLE `Train` (
`id` int(11) NOT NULL,
`callsign` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UK_callsign_train` (`callsign`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `Component` (
`id` int(11) NOT NULL,
`callsign` varchar(255) NOT NULL,
`train_FK` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UK_callsign_comp` (`callsign`),
KEY `FK_comp_train` (`train_FK`),
CONSTRAINT `FK_comp_train` FOREIGN KEY (`train_FK`) REFERENCES `Train` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `Wagon` (
`numOfSeats` int(11) NOT NULL,
`id` int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK_wagon_comp` FOREIGN KEY (`id`) REFERENCES `Component` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
So now I want to create a DAO method that returns a Train object including all of it's components. I could query the Train by it's ID and lookup the corresponding components in the Component table using the train_fk, but this is where the trouble starts. The Component
table only partially holds the data I need (in case of the Wagon obj the rest of the information lives in the Wagon
table).
In this case it's obvious that I need to query the Wagon
table for the rest of the information, but what if I have more types. How can I know what table to query for and what object to parse to?
I get that this is impossible with the current structure, but how is this done normally? What are standard solutions to handling inheritance like this in a relational database?
Thanks in advance!
PS: I'm trying to do this without the use of JPA, Hibernate or any other framework, just JDBC ;)
Upvotes: 1
Views: 501
Reputation: 36163
I would suggest to add a column on the Component table that indicates the subtype.
When you then join train with component and all subtypes you can identify on the Java side what type you have to instantiate.
The second option could be a case statement in the select:
select *,
case
when w.id is not null then 'wagon'
end as type
from train t
join component c on c.train_FK = t.id
left outer join Wagon w on w.id = c.id
Upvotes: 2