Дубликаты значений в связях ManyToOne в Spring
У меня есть связь типа ManyToOne между полями city и записью DictionaryItemCity (значение из справочника для города из нескольких полей) для структуры данных типа:
{
"id": ...,
"person": {
...
"city":
{
"id": null,
"value": "Moskow",
"label": "Moskow"
},
...
...
}
Привожу здесь только, код, имеющий отношение к проблеме, без указания всех полей сущностей:
@Entity
@Table(name = "candidates")
public class Candidate {
...
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "person_id")
private Person person;
...
}
@Entity
@Table(name = "persons")
public class Person {
...
@ManyToOne(optional = false, cascade = CascadeType.ALL)
@JoinColumn(name = "dictionary_item_city_id", nullable = false)
private DictionaryItemCity city;
...
}
@Entity
@Table(name = "dictionary_item_cities")
public class DictionaryItemCity {
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
@Column(name = "dictionary_item_city_id")
private UUID id;
@Column(name = "value", nullable = false)
private String value;
@Column(name = "label", nullable = false)
private String label;
...
Конструкторы, сеттеры, геттеры
...
}
Проблема:
Всё работает, всё сохраняется, но запись с городом в таблице dictionary_item_cities дублируется, если сохранять кандидатов с одинаковыми городами.
То есть, если сохранить 10 кандидатов с городом вида:
{
"id": null,
"value": "Moskow",
"label": "Moskow"
}
... то в таблице dictionary_item_cities будет 10 записей с разным ID:
"bcf17ed3-a762-4cd0-8462-5a824cd28357" "Moskow" "Moskow"
"..." "Moskow" "Moskow"
"..." "Moskow" "Moskow"
"..." "Moskow" "Moskow"
"..." "Moskow" "Moskow"
"..." "Moskow" "Moskow"
...
"..." "Moskow" "Moskow"
Я не знаю:
Должно ли быть именно так? Считается ли это нормальной практикой? Как вообще сформулировать будущее данную особенность для общения с коллегами в терминологии Hibernate? Это особенность наследования сущностей в Hibernate?
Как от этого избавиться? Как сделать так, чтобы при добавлении дубликата города с ID = null дубликат не добавлялся?
Можно ли считать, что в данном случае это вызвано тем, что на уровне candidate-person используется связь типа OneToOne, и поэтому город является как бы "личной собственностью" пары candidate-person?
Идеальный вариант, как бы я хотел сделать:
- Чтобы таблица dictionary_item_cities была заполнена предварительными справочными данными с городами, с уже готовыми ID...
- Которые бы передавались на фронт в виде готовых объектов для подстановки в форму (в поле выбора города)...
- А с фронта подставлялись в JSON-объект кандидата уже в готовом виде, с ID...
- И, при сохранении в базу любых кандидатов города не дублировались, и не добавлялись совсем, а только в таблице person для каждой записи подставлялись бы ID городов. Сейчас они и так подставляются, но всё же города дублируются.
Я пробовал подставлять готовые города из базы вручную, через запрос вида:
{
"id": null,
"person": {
"id": null,
...
"city":
{
"id": "bcf17ed3-a762-4cd0-8462-5a824cd28357",
"value": "Moskow",
"label": "Moskow"
},
...
...
}
Но это не даёт сохранить объект, в логах выдаётся ошибка:
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: ru.cnettcrm.entity.candidate.DictionaryItemCity; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: ru.cnettcrm.entity.candidate.DictionaryItemCity