Описание

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

Например така:

CREATE TABLE user_ employee_client {
  id INT,
  name VARCHAR,
  birthday DATE,
  occupation VARCHAR,
  salary INT,
  join DATE,
  address VARCHAR,
  DTYPE VARCHAR
}

Тоест имаме една table, в която колоните за всички класове от нашата йерархия са маркирани с различни цветове. Има и специална служебна колона DTYPE VARCHAR , където Hibernate ще съхранява името на класа Entity.

Единственото нещо, което остава да направите, е да обясните на Hibernate, че данните от класовете Entity вече се съхраняват в базата данни в една table. Това може да стане с помощта на анотацията @Inheritance :

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)

Пример за нашите класове:

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Entity
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;
}

Как се съхраняват данните

Сега нека напишем пример, в който създаваме няколко от нашите обекти и ги запазваме в базата данни:

Employee employee = new Employee();
employee.id = 101;
employee.name = "Ivanov";
employee.birthday = LocalDate.of("01-01-1999");
employee.occupation = "Programmer"
employee.salary = 100000;
employee.join = LocalDate.of("12-01-2018");
session.persist(employee);

Client client = new Client();
client.id = 102;
client.name = "Petrov";
client.birthday = LocalDate.of("15-11-1988");
client.address = "Shandara";
session.persist(client);

При запис в базата данни ще се изпълни следната SQL заявка:

INSERT INTO user_ employee_client (id, name, birthday, occupation, salary, join, DTYPE)
VALUES (101, 'Ivanov', '01-01-1999', 'Programmer', 100000, '12-01-2018', 'Employee')

INSERT INTO user_ employee_client (id, name, birthday, address, DTYPE)
VALUES (102, 'Petrov', '15-11-1988', 'Shandara', 'Client')

Когато записва данни в table, Hibernate предава само полета на обекти, които са му известни. Това означава, че неопределените колони ще бъдат NULL.

И това означава, че не можете да посочите типа NOT NULL за колоната за професия, тъй като когато клиентът се съхранява в същата table, неговата професия ще бъде NULL. Това е един от недостатъците на съхраняването на различни обекти в една и съща table.

Последното поле в SQL заявката е колоната DTYPE, която съдържа името на класа Entity. Използва се от Hibernate, когато искате да прочетете данни от вашата table.

Пример:

List<User> accounts = session.createQuery("from User").list();

Тази заявка ще върне списък на всички обекти от потребителски тип, съхранени в базата данни: потребител, служител и клиент. Въз основа на колоната DTYPE, типът на обекта ще бъде правилно определен и ще бъде създаден обект от правилния клас.

В нашия случай ще има два обекта в списъка с акаунти: тип Служител и тип Клиент.

HQL правила.