Spring boot: как сохранить отношение один-ко-многим отдельно с помощью репозитория

У меня два класса: отделение и сотрудники. У них есть отношение один ко многим, т.е. в одном отделе может быть много сотрудников.

Сотрудник не может существовать без отдела. В отделе может быть от 0 до n сотрудников.

Я получаю списки обоих этих элементов ... Эти списки могут содержать новые записи и обновленные записи.

У меня вопрос, как мне это сделать?

  1. Независимое сохранение / объединение отделов
  2. Сохраните / объедините сотрудников после шага 1. независимо (убедитесь, что идентификатор отдела есть в таблице отделов)

ИЛИ

  1. Сохранить / объединить отделы с Set<> сотрудников?

ИЛИ

Есть ли другой способ сделать это, о котором я еще не думал?

Ваши требования расплывчаты, и вы явно ничего не пробовали. Итак, попробуйте что-то, затем постарайтесь еще больше, и если это не дает того, что вы хотите, то возвращайтесь сюда, опубликуйте весь соответствующий код, точно объясните, что вы ожидаете, и что происходит вместо этого.

JB Nizet 09.08.2018 11:16

Я пробовал оба из них, но не уверен, что лучше.

Marci-man 09.08.2018 11:17

Это зависит от вашего варианта использования. Вопрос в том, действительно ли вам нужен Набор сотрудников в отделе.

Simon Martinelli 09.08.2018 11:19

Да, мне действительно нужен набор сотрудников, потому что, когда я выбираю отдел, я автоматически получаю сотрудников, поэтому мне никогда не придется напрямую выбирать сотрудников.

Marci-man 09.08.2018 11:20

В этом случае объедините отдел с множеством сотрудников.

Simon Martinelli 09.08.2018 11:26

Сколько сотрудников в каждом отделе у вас будет?

Simon Martinelli 09.08.2018 11:26

В одном отделе может быть до 10 или 12 сотрудников.

Marci-man 09.08.2018 12:47
1
7
2 196
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

У вас должно быть поле отдела в классе сотрудников. Всякий раз, когда вы меняете связь между сотрудником и отделом, вам необходимо установить employee.department и добавить / удалить сотрудника в / из соответствующей коллекции Department.employees.

Затем вам нужно только сохранить отделы, предполагая, что CascadeType правильно установлен для коллекции Department.employees.

Ответ принят как подходящий

Есть два шаблона, называемые «Репозиторий» и «Агрегат», они взяты из книги Эрика Эванса Доменно-ориентированный дизайн, и лучше всего использовать один из них.

Шаблон репозитория

  • две независимые организации (отдел и сотрудник)
  • нет отношений JPA (@OneToMany) между сущностями
  • employee просто содержит поле departmentId
  • два репозитория (departmentRepo, employeeRepo)

Если вам нужно получить отдел сотрудника, это должно быть так:

department = departmentRepo.findById(employee.departmentId)

Сохранение сущностей также осуществляется с использованием их репозиториев независимо:

newDepartment = departmentRepo.save(new Department())
newEmployee = employeeRepo.save(new Employee(newDepartment.id))

Агрегатный образец

В отличие от двух репозиториев и отсутствия связи между сущностями агрегатный шаблон использует:

  • ОДИН репозиторий (в данном случае departmentRepo)
  • Сущность department имеет соединение @OneToMany с employees (отдел содержит сотрудников).

В этом случае для получения сотрудников вам необходимо использовать репозиторий отдела:

employees = departmentRepo.findById(departmentId).employees

То же самое с сохранением: вы должны сохранить отдел, чтобы сохранить изменения в сотруднике.

Резюме

Любые комбинации этих шаблонов (наиболее распространенные: два репозитория и отношения JPA между сущностями) приводят к действительно сложным проблемам с обслуживанием в будущем.

В большинстве случаев я предпочитаю шаблон репозитория: репозиторий для каждой сущности и отсутствие связей между сущностями.

В вашем случае я бы выбрал шаблон репозитория.

но это означает, что в случае Шаблон репозитория я не могу обеспечить целостность данных на уровне базы данных, верно?

Marci-man 09.08.2018 12:51

Вы по-прежнему можете создавать ограничения в БД. Но часто в этом нет необходимости (например, это затрудняет тестирование, потому что вам нужно создать слишком много сущностей, чтобы удовлетворить всем ограничениям). Чего нельзя использовать, так это каскадного удаления, но это тоже редкий случай, и с ним можно справиться «вручную».

Max Farsikov 09.08.2018 12:54

Вы можете определить классы сущностей, как показано ниже:

@Entity
public class Department {
  @NotNull
  @Id
  private String depId;
  private String depName;

  @OneToMany(mappedBy = "department", cascade = CascadeType.ALL, fetch = FetchType.LAZY,
  orphanRemoval = true)
  private Set<Employee> employees;
}

@Entity
public class Employee {

  @Id
  private String employeeId;
  private String employeeName;
  @ManyToOne
  @JoinColumn(name = "dep_id", nullable = true)
  private Department department;
}

Сохранение значения отдела обнуляемым для сотрудника и сотрудника в отделе. Вам нужно будет определить репозиторий для этих объектов для извлечения / сохранения. Также, если вы собираетесь использовать набор сотрудников, убедитесь, что он переопределяет методы hashcode () и equals () класса объекта.

Другие вопросы по теме

Общий кеш Infinispan 2LC
Интеграция Spring Boot + Hibernate (не Spring Data JPA) в Spring Boot 2.0 или выше
Ошибка при создании bean-компонента с именем 'ModelAccess' Не удалось ввести автоматически подключенные зависимости; Не удалось выполнить автоматическое подключение поля
Невозможно получить возвращаемое значение хранимой процедуры через Java
Как получить точный поиск с помощью lucene
Ошибка ведения журнала jboss при развертывании приложения Springboot на сервере jboss
HibernateJPaVendorAdapter: невозможно преобразовать значение типа String в требуемый тип 'org.springframework.orm.jpa.vendor.Database' ENitty
Hibernate выбрасывает com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: проверьте руководство для правильного синтаксиса для использования около времени localTime
Hibernate - пользовательский запрос не нашел сущность по дочернему параметру для однонаправленного отношения ManyToOne
Избегайте бесконечной рекурсии (StackOverflowError) без потери информации с помощью JPA и Jackson JSON