Сохранение сущности с @JoinColumn, не указывающей на какой-либо атрибут ID - PullRequest
0 голосов
/ 09 мая 2019

У меня есть объект ConfigurationEntity, имеющий атрибут dayOfTheWeek, который может иметь значение 1-7.Когда клиент выбирает GET .../configuration, он хочет иметь как имена, так и коды (1-7).Относительно декомпозиции я создал DictionaryEntity, который сопоставляется с таблицей, в которой хранятся значения

id   | group        | name    | code
123  | dayOfTheWeek | Monday  | 1
124  | dayOfTheWeek | Tuesday | 2
etc..

. Я определил ConfigurationEntity как

(я опускаю некоторые детали и аннотации, которые, как мне кажется,не важны в проблеме)

class ConfigurationEntity {
  @Id
  private Long id;

  @ManyToOne
  @JoinColumn(column = "dayOfTheWeek", referenceColum = "code", table = "dictionary")
  @Where("dictionary.group = 'dayOfTheWeek'")
  @JsonIgnore
  private DictionaryEntity dayOfTheWeekDictionary;

  @JsonProperty
  public Number getDayOfTheWeek() {
    return this.dayOfTheWeekDictionary.code;
  }

  @JsonProperty
  public String getDayOfTheWeekDescription() {
    return this.dayOfTheWeekDictionary.name;
  }
}

И это работает, что приводит к ответу на GET:

{
  "id": 1,
  "dayOfTheWeek": 1,
  "dayOfTheWeekDescription": "Monday"
}

Проблема в том, что клиент хочет отправить некоторые изменения в ConfigurationEntity и отправляетследующий запрос PATCH:

{
  "id": 1,
  "dayOfTheWeek": 2
}

Hibernate / JPA (я обычно путаюсь, кто что делает, что именно) может сохранить это (с некоторыми взломами), но repository.save(entity) возвращает мне записи с dayOfTheWeekDictionary равнымnull.То же самое касается repository.getById(id).После повторного вызова GET клиент получает правильно сопоставленную / присоединенную запись.

Вопрос в том, как сохранить сущность, зная только dictionary.code, чтобы hibernate мог найти соответствующий DictionaryEntity для этой записи?

Я понимаю, что DictionaryEntity на самом деле имеетсоставной ключ (группа, код).Я могу добавить этот ключ, но, тем не менее, клиент знает только одну часть ключа, а сущность знает вторую часть (предложение @Where).Я могу получить DictionaryEntity самостоятельно, но что если у меня 100 таблиц с 200 полями, объединенными с таблицей dictionary?Я хочу, чтобы решение было абстрактным / общим.

1 Ответ

1 голос
/ 09 мая 2019

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

Во-первых: вам не нужна таблица базы данных, чтобы указать, что 1 - понедельник, а 2 - вторник.Это должно быть просто жестко закодировано в вашем коде: это никогда не изменится.Все, что вам нужно, это правильно определенный перечисление и пользовательский сериализатор JSON, который сериализует экземпляр этого перечисления в объект с кодом и именем дня:

"dayOfTheWeek": {
  "code": 1,
  "name": "Monday"
}

Теперь для API, позволяющего изменятьобъект конфигурации.Нет абсолютно никаких причин позволять любому клиенту указывать название дня.Цель состоит в том, чтобы изменить объект конфигурации, у этого объекта есть день недели, который однозначно и однозначно идентифицируется числовым кодом.Итак, чтобы изменить день объекта конфигурации, все, что вам нужно, это новый код дня.Отправка нового имени дня является излишней и запутанной (как показывает ваш вопрос).Поэтому спроектируйте входные данные API как объект, требующий кода дня, но без имени дня.

В качестве примера, см. Github REST API.Если вы получите вопрос , вы получите, как часть проблемы в ответе, объект правопреемника с большим количеством деталей о правопреемнике: логин, идентифицирующий правопреемника, а также его / ее авторитет, URL-адреса,и т. д.

Но если вы отправляете новую проблему, единственной необходимой информацией является идентификатор правопреемника проблемы.Граватар и URL-адреса цессионария бесполезны, и их отправка может привести к путанице, поскольку API не хочет (и не может) изменять данные цессионария.Итак, что API принимает в качестве ввода ?Объект, содержащий только строку для правопреемника, и эта строка содержит только то, что однозначно идентифицирует правопреемника: его / ее логин.

Заменить «проблема» на «объект конфигурации», а «цессионарий» на «деньнедели ", и у вас та же ситуация, что и у вас.

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