Хотел написать в одной статье о типах связей в реляционных БД, и как их реализовать в JPA
Однако в одну статью с примерами кода не поместилось, поэтому разделил на две статьи и создал отдельные репозитории:
🐘 sandbox-postgresql
🌱 sandbox-spring-data-jpa
Если в статье SQL код неправильно отображается, нужно обновить Telegram.
❓ Какие существуют типы связей в реляционных БД?
Рассмотрим на примере нашей любимой доменной модели — Библиотеки
У нас будут две сущности — Книга, Автор
В зависимости от наших требований к системе, мы будем строить нужную связь между сущностями
Требование:
В нашей системе мы хотим чтобы у одной книги был только один автор. А также, чтобы автор имел возможность написать только одну книгу.
Решение:
Для реализации такой модели данных нам подойдет отношение One to One [читается как “один автор — одна книга”]:
CREATE TABLE authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
name VARCHAR(64) NOT NULL
);
CREATE TABLE books
(
id BIGSERIAL NOT NULL PRIMARY KEY,
title VARCHAR(128) NOT NULL,
author_id BIGINT NOT NULL UNIQUE REFERENCES authors (id)
);
Здесь важно установить UNIQUE constraint, в нашем случае на поле author_id, чтобы разные книги не могли ссылаться на одного автора.
Также вместо author_id, можно сделать book_id в таблице authors, и наше требование тоже выполнится.
Таким образом мы выбираем, кто будет владельцем связи, Book или Author [об этом будет подробнее в статье про Spring Data JPA, но если кратко, тот у кого в таблице foreign key]
Пример доступен на 🐙Github
Требование:
В нашей системе мы хотим чтобы у одной книги был только один автор. Однако, автор может написать сколько угодно книг.
Решение:
В этом случае нам подойдет отношение One to Many [читается как “один автор — множество книг”]
Иногда выделяют отношение Many to One [читается как “множество книг — один автор”], разницы в реализации между ними нету, мы только меняем акцент, когда говорим что с чем связано
CREATE TABLE authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
name VARCHAR(64) NOT NULL
);
CREATE TABLE books
(
id BIGSERIAL NOT NULL PRIMARY KEY,
title VARCHAR(128) NOT NULL,
author_id BIGINT NOT NULL REFERENCES authors (id)
);
Единственная разница в реализации между One to One и One to Many, что теперь у нас нету UNIQUE constraint для поля author_id
Также если мы сделаем book_id в таблице authors вместо author_id в таблице books, то наше требование не выполнится, потому что тогда автор сможет иметь только одну книгу
[Поэтому в JPA у аннотации ManyToOne нету параметра mappedBy, потому что такая сущность точно является владельцем связи, т.е. имеет foreign key на другую сущность]
Пример доступен на 🐙Github
Требование:
В нашей системе мы хотим чтобы у одной книги было сколько угодно авторов. А также, автор может написать сколько угодно книг.
Решение:
Здесь нам подходит Many to Many [читается как “множество авторов — множество книг”]:
CREATE TABLE authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
name VARCHAR(64) NOT NULL
);
CREATE TABLE books
(
id BIGSERIAL NOT NULL PRIMARY KEY,
title VARCHAR(128) NOT NULL
);
CREATE TABLE books_authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
book_id BIGINT NOT NULL REFERENCES books (id),
author_id BIGINT NOT NULL REFERENCES authors (id),
UNIQUE (book_id, author_id)
);
Создается дополнительная таблица books_authors, указывающая нужные связи между сущностями
Не стоит также забывать о добавлении UNIQUE constraint’a на связь book_id и author_id, чтобы связь была уникальной
Пример доступен на 🐙Github
#sandbox_postgresql #relationships
➿ Меню
➿ Подпишись: @developer_sandbox
Однако в одну статью с примерами кода не поместилось, поэтому разделил на две статьи и создал отдельные репозитории:
🐘 sandbox-postgresql
🌱 sandbox-spring-data-jpa
Если в статье SQL код неправильно отображается, нужно обновить Telegram.
❓ Какие существуют типы связей в реляционных БД?
Рассмотрим на примере нашей любимой доменной модели — Библиотеки
У нас будут две сущности — Книга, Автор
В зависимости от наших требований к системе, мы будем строить нужную связь между сущностями
Требование:
В нашей системе мы хотим чтобы у одной книги был только один автор. А также, чтобы автор имел возможность написать только одну книгу.
Решение:
Для реализации такой модели данных нам подойдет отношение One to One [читается как “один автор — одна книга”]:
CREATE TABLE authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
name VARCHAR(64) NOT NULL
);
CREATE TABLE books
(
id BIGSERIAL NOT NULL PRIMARY KEY,
title VARCHAR(128) NOT NULL,
author_id BIGINT NOT NULL UNIQUE REFERENCES authors (id)
);
Здесь важно установить UNIQUE constraint, в нашем случае на поле author_id, чтобы разные книги не могли ссылаться на одного автора.
Также вместо author_id, можно сделать book_id в таблице authors, и наше требование тоже выполнится.
Таким образом мы выбираем, кто будет владельцем связи, Book или Author [об этом будет подробнее в статье про Spring Data JPA, но если кратко, тот у кого в таблице foreign key]
Пример доступен на 🐙Github
Требование:
В нашей системе мы хотим чтобы у одной книги был только один автор. Однако, автор может написать сколько угодно книг.
Решение:
В этом случае нам подойдет отношение One to Many [читается как “один автор — множество книг”]
Иногда выделяют отношение Many to One [читается как “множество книг — один автор”], разницы в реализации между ними нету, мы только меняем акцент, когда говорим что с чем связано
CREATE TABLE authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
name VARCHAR(64) NOT NULL
);
CREATE TABLE books
(
id BIGSERIAL NOT NULL PRIMARY KEY,
title VARCHAR(128) NOT NULL,
author_id BIGINT NOT NULL REFERENCES authors (id)
);
Единственная разница в реализации между One to One и One to Many, что теперь у нас нету UNIQUE constraint для поля author_id
Также если мы сделаем book_id в таблице authors вместо author_id в таблице books, то наше требование не выполнится, потому что тогда автор сможет иметь только одну книгу
[Поэтому в JPA у аннотации ManyToOne нету параметра mappedBy, потому что такая сущность точно является владельцем связи, т.е. имеет foreign key на другую сущность]
Пример доступен на 🐙Github
Требование:
В нашей системе мы хотим чтобы у одной книги было сколько угодно авторов. А также, автор может написать сколько угодно книг.
Решение:
Здесь нам подходит Many to Many [читается как “множество авторов — множество книг”]:
CREATE TABLE authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
name VARCHAR(64) NOT NULL
);
CREATE TABLE books
(
id BIGSERIAL NOT NULL PRIMARY KEY,
title VARCHAR(128) NOT NULL
);
CREATE TABLE books_authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
book_id BIGINT NOT NULL REFERENCES books (id),
author_id BIGINT NOT NULL REFERENCES authors (id),
UNIQUE (book_id, author_id)
);
Создается дополнительная таблица books_authors, указывающая нужные связи между сущностями
Не стоит также забывать о добавлении UNIQUE constraint’a на связь book_id и author_id, чтобы связь была уникальной
Пример доступен на 🐙Github
#sandbox_postgresql #relationships
➿ Меню
➿ Подпишись: @developer_sandbox