Проблеми с консервацията

Днес ще имаме нова и супер интересна схема - използване на функциите на Hibernate за запазване на йерархията на класовете в базата данни.

Йерархията на класовете е набор от класове, свързани един с друг чрез връзка на наследяване.

Представете си, че имате три класа, които искате да съхраните в базата данни:

class User {
  int id;
  String name;
  LocalDate birthday;
}
class Employee extends User {
 	String occupation;
 	int salary;
 	LocalDate join;
}
class Client extends User {
   String address;
}

Класовете се наследяват един от друг. И най-интересното е, че искате да използвате Hibernate, за да съхранявате обекти от тези класове в базата данни.

Видове разтвори

Hibernate има 4 възможни начина, по които може да асоциира йерархия на класове с таблици в база данни:

  • MappedSuperclass
  • единична маса
  • Присъединена маса
  • Таблица за клас

Всяка стратегия предполага собствена структура на table в базата данни. Понякога са доста сложни. Но заявките за HQL към тях са много прости. Това е точно случаят, в който предимствата на Hibernate се проявяват ясно.

Никога не съм чувал тези термини преведени на руски, така че препоръчвам да ги произнасяте и на английски.

По-долу ще анализираме Howво означава всеки от тях.

@MappedSuperClass

Нека започнем с най-простото решение - в базата данни имате отделни таблици за всеки клас . Например тези:

CREATE TABLE user {
  id INT,
  name VARCHAR,
  birthday DATE
}
CREATE TABLE employee {
  id INT,
  name VARCHAR,
  birthday DATE,
  occupation VARCHAR,
  salary INT,
  join DATE
}
CREATE TABLE client {
  id INT,
  name VARCHAR,
  birthday DATE,
  address VARCHAR
}

Само вие знаете , че класовете за тези таблици са свързани в йерархия . Ако искате Hibernate да знае и за това, трябва да добавите анотацията @MappedSuperclass към родителския клас . Без него Hibernate просто ще игнорира полетата и анотациите на родителския клас.

Класовете с тази анотация ще изглеждат така:

@MappedSuperclass
class User {
  int id;
  String name;
  LocalDate birthday;
}
@Entity
class Employee extends User {
 	String occupation;
 	int salary;
 	LocalDate join;
}
@Entity
class Client extends User {
   String address;
}

Това е най-примитивният начин за свързване на йерархията на класовете и базата данни. Този подход всъщност ви позволява само да избегнете дублиращи се полета в класове.

Заявките към бази данни в HQL ще върнат само обекта, чийто тип е посочен изрично. Не можете да напишете заявка за база данни в HQL и да получите списък с всички потребители: потребител, служител, клиент.