Добрый день!
Помогите пожалуйста понять как правильно строить архитектуру проекта и работу с БД.
Объясняю суть проблемы.
Есть приложение написанное на Java с использованием Spring, Hibernate.
Допустим есть БД по школе, состоящая из нескольких таблиц, связанных между собой:
//пользователи(преподаватели+директора)
CREATE TABLE appuser (
appuser_id serial NOT NULL,
fio VARCHAR(50) UNIQUE,
PRIMARY KEY (appuser_id)
);
CREATE TABLE school (
school_id serial NOT NULL,
school_number VARCHAR(10) UNIQUE,
director INT, /* директор */
PRIMARY KEY (school_id)
);
ALTER TABLE school ADD CONSTRAINT school_fk0 FOREIGN KEY (director) REFERENCES appuser(appuser_id);
CREATE TABLE subject (
subject_id serial NOT NULL,
description VARCHAR(30) UNIQUE,
PRIMARY KEY (subject_id)
);
//учитель может читать разные предметы в разной школе
CREATE TABLE teacher_school_subject (
tss_id serial NOT NULL,
teacher INT,
school INT,
subject INT,
PRIMARY KEY (tss_id)
);
ALTER TABLE teacher_school_subject ADD CONSTRAINT teacher_school_subject_fk0 FOREIGN KEY (teacher) REFERENCES appuser(appuser_id);
ALTER TABLE teacher_school_subject ADD CONSTRAINT teacher_school_subject_fk1 FOREIGN KEY (school) REFERENCES school(school_id);
ALTER TABLE teacher_school_subject ADD CONSTRAINT teacher_school_subject_fk2 FOREIGN KEY (subject) REFERENCES subject(subject_id);
Сущности(привожу только часть параметров чтобы не загромождать страницу):
@Entity
@Table(name = "teacher_school_subject")
public class TeacherSchoolSubject implements Serializable {
@JoinColumn(name = "teacher", referencedColumnName = "appuser_id")
@ManyToOne(fetch = FetchType.EAGER)
private Appuser teacher;
@JoinColumn(name = "school", referencedColumnName = "school_id")
@ManyToOne(fetch = FetchType.EAGER)
private School school;
@JoinColumn(name = "subject", referencedColumnName = "subject_id")
@ManyToOne(fetch = FetchType.EAGER)
private Subject subject;
}
@Entity
@Table(name = "school")
public class School implements Serializable {
@JoinColumn(name = "director", referencedColumnName = "appuser_id")
@ManyToOne(fetch = FetchType.EAGER)
private Appuser director;
}
public interface TeacherSchoolSubjectRepository
extends PagingAndSortingRepository<TeacherSchoolSubject, Integer> {
@Query(value = "SELECT * FROM teacher_school_subject", nativeQuery = true)
List<TeacherSchoolSubject> findAllTSS();
}
Например я хочу сделать выборку всех записей из teacher_school_subject.
При этом я получаю список объектов TeacherSchoolSubject.
Однако этот запрос вызывает за собой множество отдельных уточняющих запросов по каждой из таблиц после основного SELECT * запроса.
Видел что можно использовать @SqlResultSetMapping и запрос типа
@Query(value = "SELECT * FROM teacher_school_subject AS tss "
+ "INNER JOIN appuser au ON au.appuser_id=tss.teacher "
+ "INNER JOIN school s ON s.school_id=tss.school "
+ "INNER JOIN subject sub ON sub.subject_id=tss.subject ", nativeQuery = true)
List<TeacherSchoolSubject> findAllTSSJoin();
Правильный ли это подход?
Или не переживать по поводу того что идет множество запросов?
Как вообще правильно работать осуществлять выборку данных с тем чтобы подхватывались и связанные данные из других таблиц?
Всегда ли стоит использовать FetchType.EAGER в связях ManyToOne на стороне Many?
Ведь у меня фактически получается глубина вложенности
TeacherSchoolSubject.school -> School.director -> Appuser
, но она ж может быть и больше. И получается что при выборе из верхней таблицы Hibernate вынужден делать по каждой строке уточняющие запросы на выборку более глубоколежащих данных.