← Назад к вопросам

Что такое иерархическая таблица?

2.0 Middle🔥 171 комментариев
#ООП#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Иерархическая таблица в базе данных

Иерархическая таблица — это таблица, в которой записи имеют отношение типа "родитель-потомок", создавая древовидную структуру. Самый распространённый способ реализации — самоссылающийся внешний ключ.

Структура иерархической таблицы

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

CREATE TABLE employees (
    id BIGINT PRIMARY KEY,
    name VARCHAR(255),
    manager_id BIGINT REFERENCES employees(id) ON DELETE SET NULL
);

Здесь manager_id указывает на другого сотрудника (руководителя). Каждый сотрудник может быть руководителем нескольких других.

В Java с Hibernate

@Entity
@Table(name = "employees")
public class Employee {
    @Id
    private Long id;
    
    @Column(name = "name")
    private String name;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "manager_id")
    private Employee manager; // Ссылка на руководителя
    
    @OneToMany(mappedBy = "manager", cascade = CascadeType.ALL)
    private List<Employee> subordinates = new ArrayList<>(); // Подчинённые
}

Примеры иерархических структур

  • Организационная структура — CEO → Руководители → Сотрудники
  • Файловая система — директории и подпапки
  • Категории товаров — категория → подкатегория → подподкатегория
  • Комментарии на форуме — коммент → ответ → ответ на ответ
  • Меню приложения — пункт меню → подпункт

Способы работы с иерархией

1. Рекурсивный обход (простой способ)

public List<Employee> getAllSubordinates(Employee manager) {
    List<Employee> result = new ArrayList<>(manager.getSubordinates());
    for (Employee subordinate : manager.getSubordinates()) {
        result.addAll(getAllSubordinates(subordinate));
    }
    return result;
}

Минус: множество запросов к БД, опасность StackOverflowError при глубокой иерархии.

2. CTE (Common Table Expression) — рекурсивный запрос SQL

WITH RECURSIVE employee_tree AS (
    SELECT id, name, manager_id, 1 as level
    FROM employees
    WHERE manager_id IS NULL -- Начинаем с корня
    
    UNION ALL
    
    SELECT e.id, e.name, e.manager_id, et.level + 1
    FROM employees e
    INNER JOIN employee_tree et ON e.manager_id = et.id
)
SELECT * FROM employee_tree;

Этот способ очень эффективен для больших иерархий.

3. Путь в каждой записи (Materialized Path)

CREATE TABLE employees (
    id BIGINT PRIMARY KEY,
    name VARCHAR(255),
    path VARCHAR(1000) -- 1/5/12/45
);

Путь хранится как строка с идентификаторами предков. Позволяет быстро найти всех потомков через LIKE.

4. Nested Sets (вложенные множества)

Каждый узел имеет left и right значения. Потомки находятся между этими значениями.

CREATE TABLE employees (
    id BIGINT PRIMARY KEY,
    name VARCHAR(255),
    lft INT,
    rgt INT
);

Очень эффективно для чтения, но сложнее для вставок и удалений.

Производительность

СпособЧтение потомковВставка узлаСложность
Self-joinO(N) запросовO(1)Простая
CTEO(1) запросO(1)Средняя
Materialized PathO(1) запросO(N) обновленийСредняя
Nested SetsO(1) запросO(N) обновленийСложная

Выбор метода

  • Читаешь часто, пишешь редко? → Nested Sets
  • Нужна простота? → Self-join с CTE
  • Часто менеется структура? → Materialized Path
  • Стандартное решение? → Self-join (как в примере выше)

Вывод: Иерархическая таблица — это основной способ хранить древовидные данные в реляционной БД. Выбор реализации зависит от сценария использования и требований к производительности.