Сохранение сущности с отношением один ко многим - PullRequest
2 голосов
/ 30 марта 2019

Я думаю, что у меня плохая настройка для моей базы данных гибернации.У меня есть Citizen сущности, которые имеют отношения один ко многим с WeeklyCare сущностями.Ниже приведен соответствующий код.

Гражданин:

@Entity
@Table(name = "citizens")
public class Citizen {
@Id
@Size(max = 10, min = 10, message = "CPR must be exactly 10 characters")
private String cpr;

@OneToMany()
@JoinColumn(name = "cpr")
private List<WeeklyCare> weeklyCare;
}

WeeklyCare:

@Entity
public class WeeklyCare {
@EmbeddedId
private WeeklyCareIdentifier weeklyCareIdentifier;
}

WeeklyCareIdentifier:

@Embeddable
public class WeeklyCareIdentifier implements Serializable {

@NotNull
@Size(max = 10, min = 10, message = "CPR must tbe exactly 10 characters")
private String cpr;

@NotNull
private Integer week;

@NotNull
private Integer year;
}

У меня возникают проблемы, когдаЯ хочу сохранить данные в базу данных:

  1. Сначала я не могу сохранить WeeklyCare, потому что для этого требуется Citizen.
  2. Когда я отправляю граждан в свой бэкэнд, объекты содержат список WeeklyCare.Когда я пытаюсь спасти граждан, мне выдается эта ошибка: Unable to find Application.Models.WeeklyCare with id Application.Models.WeeklyCareIdentifier@b23ef67b

Я могу решить эту проблему, очистив список WeeklyCare на Citizen перед его сохранением, а затемсохранение списка WeeklyCare после, но это кажется ужасным способом сделать это.

Я думаю, я хочу, чтобы hibernate игнорировал список WeeklyCare, когда он сохраняет Citizen, но подтверждает егокогда он получает Citizen.Это возможно?Или есть еще лучший способ сделать это?Спасибо.

1 Ответ

0 голосов
/ 30 марта 2019
  1. Сначала я не могу сохранить WeeklyCare, потому что для этого требуется гражданин.

У вас есть идентификатор "cpr", используемый в двух объектах:

  • это основной идентификатор для Citizen
  • это часть составного идентификатора для WeeklyCare

Теоретически можно создать список WeeklyCare (не так, как это моделируется сейчас), а затем обновите ассоциации каждого WeeklyCare до Citizen.

Когда я отправляю граждан на свой сервер, объекты содержат список WeeklyCare.Когда я пытаюсь спасти граждан, это дает мне такую ​​ошибку: Невозможно найти Application.Models.WeeklyCare с идентификатором Application.Models.WeeklyCareIdentifier@b23ef67b

Лучший способ сопоставить One-Ассоциация To-Many является двунаправленной.Это также избавит вас от некоторых ненужных запросов, генерируемых Hibernate при использовании @OneToMany только с @JoinColumn.

1) Удалите cpr из класса WeeklyCareIdentifier (и, возможно, переименуйте класс).

@Embeddable
public class WeeklyCareIdentifier implements Serializable {

  @NotNull
  private Integer week;

  @NotNull
  private Integer year;

  //constructors, getters, setters
}

2) Удалите составной @EmbeddedId в пользу поля Длинный идентификатор:

@Entity
public class WeeklyCare {

  @Id
  @GeneratedValue
  private Long id;

  @Embedded
  private WeeklyCareIdentifier weeklyCareIdentifier;

  //constructors, getters, setters
}

3) Перейдите к двунаправленному отображению:

@Entity
@Table(name = "citizens")
public class Citizen {
  @Id
  @Size(max = 10, min = 10, message = "CPR must be exactly 10 characters")
  private String cpr;

  @OneToMany(
      mappedBy = "citizen",
      cascade = CascadeType.ALL, //cascade all operations to children
      orphanRemoval = true //remove orphaned WeeklyCare if they don't have associated Citizen
  )
  private List<WeeklyCare> weeklyCares = new ArrayList<>(); //init collections to avoid nulls

    //constructors, getters, setters

    //add utility methods to manipulate the relationship

    public void addWeeklyCare(WeeklyCare weeklyCare) {
      weeklyCares.add(weeklyCare);
      weeklyCare.setCitizen(this);
    }

    public void removeWeeklyCare(WeeklyCare weeklyCare) {
      weeklyCares.remove(weeklyCare);
      weeklyCare.setCitizen(null);
    }
}

и:

@Entity
public class WeeklyCare {

    @Id
    @GeneratedValue
    private Long id;

    //having reference to the citizen entity from WeeklyCare
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "citizen_cpr")
    private Citizen citizen;

    @Embedded
    private WeeklyCareIdentifier weeklyCareIdentifier;

    //constructors, getters, setters
}

Я бы также рекомендовал использовать длинные идентификаторы для сущностей, даже если cpr уникален и так далее.Преобразуйте cpr в обычный столбец и введите столбец сгенерированных БД идентификаторов, который вы используете для присоединения во внутреннем домене, и рассматривайте cpr как столбец данных, ориентированных исключительно на пользователя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...