Как я могу сопоставить сотрудников с расписаниями во взаимоотношениях «Многие ко многим» (или «Один ко многим») с JPA Spring Boot

#java #spring-boot #jpa

Вопрос:

Я не могу найти способ сопоставить некоторые сущности с моими таблицами SQL. У меня есть таблица СОТРУДНИКОВ (с идентификатором сотрудника PK), таблица DAYS_OF_WEEK (с идентификатором дня pk_of_week) и таблица EMPLOYEES_SCHEDULES (с составным PK идентификатора сотрудника, идентификатором дня_of_week и временем начала, которые являются первыми двумя атрибутами, относящимися к указанным таблицам, а время окончания является единственным атрибутом, не относящимся к PK).

 EMPLOYEES
PK  employee_id
    role_id     FK

DAYS_OF_WEEK
PK  day_of_week_id
    name

EMPLOYEES_SCHEDULES
PK | employee_id    FK
   | day_of_week_id FK
   | start_time
     end_time
 

Диаграмма классов, которой я должен следовать, говорит, что у сотрудника связано 0 или много объектов расписания сотрудников, и что у расписания сотрудников связано 1 или много объектов дня недели. Итак, классы в Java должны выглядеть следующим образом:

 @Entity
@Table(name = "EMPLOYEES")
public class Employee {
    @Id
    @Column(name = "employee_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int employeeId;

    @OneToOne
    @JoinColumn(name = "role_id", referencedColumnName = "role_id")
    private Role role;
    
    // I don't know how to map this
    private List<EmployeeSchedule> employeeSchedule;
}

@Entity
@Table(name = "EMPLOYEES_SCHEDULES")
public class EmployeeSchedule {
    @Id
    @Column(name = "start_time")
    private LocalDate startTime;

    @Basic
    @Column(name = "end_time")
    private LocalDate endTime;
    
    // I don't know how to map this
    private List<DayOfWeek> dayOfWeek;
}

@Entity
@Table(name = "DAYS_OF_WEEK")
public class DayOfWeek {
    @Id
    @Column(name = "day_of_week_id")
    private byte dayId;

    @Basic
    @Column(name = "name")
    private String name;
}   
 

Я знаю, что день недели, вероятно, можно было бы заменить перечислением, но смысл этого поста не в этом. Если возможно, пожалуйста, не предлагайте изменять структуру диаграммы классов, потому что я должен использовать ее строго (и отношения не должны быть двунаправленными). Но достаточно ли таблиц, которые я сделал, для сопоставления классов? Если да, то как я могу их сопоставить?

Ответ №1:

Вы добавляете что-то вроде этого:

  @OneToMany(cascade = CascadeType.ALL, mappedBy = "employeeSchedule")
private List<DayOfWeek> dayOfWeek=new ArrayList<>();
 

в ваш список дней.
Затем вы добавляете атрибут в entity DayOfWeek как:

     @JoinColumn(name = "NAME_OF_COLUMN", referencedColumnName = "NAME_OF_REFRENECED_COLUMN")
    @ManyToOne(optional = false)
    private EmployeeSchedule employeeSchedule=new ArrayList<>();
 

Обратите внимание, что имя атрибута в entity DayOfWeek должно совпадать с определением «Сопоставлено» в entity EmployeeSchedule. Кроме того, вам необходимо инициализировать список.
Теперь я заметил, что у вас тот же вопрос к сущности сотрудника.
Таким образом, как описано, вы должны добавить аннотацию в список. Поскольку аннотации ZeroToMany не существует, вы используете OneToMany, потому что эта аннотация описывает классы сущностей соединения beetwen, а не базу данных. Вы не можете подключить 0 сущностей ко многим сущностям. Итак, следующая аннотация описывает ваше соединение между таблицами.
Добавление этого в список:

  @OneToMany(cascade = CascadeType.ALL, mappedBy = "employee")
private List<EmployeeSchedule> employeeSchedule=new ArrayList<>();
 

И добавление этого в сущность сотрудника:

 @JoinColumn(name = "NAME_OF_COLUMN", referencedColumnName = "NAME_OF_REFRENECED_COLUMN")
@ManyToOne(optional = false)
private Employee employee;
 

Комментарии:

1. Я думаю, что сделал то, что вы сказали, но у меня возникла ошибка: Не удалось найти столбец с логическим именем: day_of_week_id в org.hibernate.mapping. Таблица(employees_schedules) и связанные с ней супертабли и второстепенные таблицы-это потому, что они имеют одно и то же имя в обеих таблицах?

2. Определенно нет, я всегда работал с одноименными столбцами(первичный и внешний ключ) и у меня не было никаких проблем. Вы уверены, что это имя столбца в таблице базы данных? Трудно вот так пытаться угадать, что это может быть. Я не знаю, какую базу данных вы используете, но проверьте, нет ли заглавных букв.

3. Это. Если бы это было не так, IntelliJ сказал бы мне. Я посмотрю, что еще я могу сделать, спасибо за помощь!

4. Я знаю, что произошло. Я на самом деле ищу объяснение и базу данных, и меня поражает одна вещь. Если в таблице EmployeeSchedule у вас есть сложный первичный ключ со значениями dayOfWeak, employee и startTime, как у одного @Entity EmployeeSchedule может быть больше? Также в описании объясняется, что в ваших компонентах сущности нет атрибута, связанного со столбцом в базе данных

5. Вы имеете в виду, как кортеж сотрудников может иметь более одного кортежа, связанного в employees_shedules? Благодаря составному ключу два разных сотрудника могут начать работать в один и тот же час и день. Я думаю, что структура таблицы работает, что бы вы изменили в ней?