Как обращаться с наследованием в реляционной базе данных

0

Мне сложно понять, как наследование работает с реляционными базами данных.

Предположим, что у меня есть следующие классы:

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 ...  
}

Поезд создается из компонентов (List), и в этом примере есть несколько подклассов компонентов (только Wagon).

Чтобы этого не произошло, я подумал, что структура Table Per Type Inheritance будет подходящей, но в этом я столкнулся с проблемами.

Моя структура базы данных:

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;

Поэтому теперь я хочу создать метод DAO, который возвращает объект Train, включая все его компоненты. Я мог бы запросить поезд по его идентификатору и найти соответствующие компоненты в таблице Component с помощью train_fk, но в этом проблема начинается. В таблице Component только частично хранятся данные, которые мне нужны (в случае Wagon obj остальная часть информации живет в таблице Wagon).

В этом случае очевидно, что мне нужно запросить таблицу Wagon для остальной информации, но что, если у меня больше типов. Как я могу узнать, в какой таблице запрашивать и какой объект обрабатывать?

Я понимаю, что это невозможно с текущей структурой, но как это делается обычно? Каковы стандартные решения для обработки наследования, подобные этому в реляционной базе данных?

Заранее спасибо!

PS: Я пытаюсь сделать это без использования JPA, Hibernate или любой другой структуры, просто JDBC;)

Теги:
inheritance
dao
relational-database

1 ответ

1
Лучший ответ

Я бы предложил добавить столбец в таблице Component, который указывает подтип.

Когда вы затем присоединяетесь к поезду с компонентом и всеми подтипами, вы можете идентифицировать на стороне Java то, что вам нужно создать.

Второй вариант может быть аргументом case в 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
  • 0
    Я думал об этом, но это кажется немного громоздким, не так ли? Мне любопытно, есть ли более эффективный способ сделать это, или это рекомендуемый образец для этой ситуации.
  • 0
    На мой взгляд, это лучшее и наиболее понятное решение. Чтобы избежать столбца, вы можете использовать оператор запроса в запросе, чтобы проверить, какой подтип строки. Но это не очевидно, что он делает.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню