У меня есть отношение @ OneToMany , где сторона @ Many должна быть уникальной в БД.Каждый раз, когда я пытаюсь сохранить сущность @ One с уже существующей сущностью @ Many , hibernate снова пытается сохранить сторону @ Many и нарушает целостность БД,Мне нужно автоматически проверить, существует ли сторона @ Many , и если это так, связать только 2 объекта.
Рассмотрим Studio объект, который может иметь много Тэг объектов.Каждый тег уникален в БД и может быть связан со многими Studio (и другими объектами). Tag связан с данным Studio только один раз.В настоящее время, если я сохраню 2 разных Studios с одним и тем же тегом , тег тег будет вставлен в БД дважды, что нарушает его целостность.Как мне спроектировать отношения, чтобы обеспечить уникальность стороны @ Many ?Я могу проверить это вручную в слое DAO, но я надеялся, что hibernate позаботится об этом (есть несколько свойств, похожих на Tag, выполнение проверки вручную сделало бы код болезненным для чтения / записи)
У меня есть 5 сущностей с одинаковыми свойствами, которые сгруппированы в общего родителя:
public abstract class AbstractMovieEntity<T extends AbstractMovieEntity> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
@NonNull
@Column(unique = true, nullable = false)
protected String name;
@EqualsAndHashCode.Exclude
@OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
protected Set<EntityTag> tags = new HashSet<>();
...
Студия - это специализация вышеупомянутого
@EqualsAndHashCode(callSuper=true)
@Getter
@Setter
@Entity
@NoArgsConstructor
public class Studio extends AbstractMovieEntity<Studio> {
...
}
Я написал тест для имитации фактическогоapplication
@Autowired
private EntityManager entityManager;
@Test
public void studioTagsAreNotDuplicated() {
Studio warners = new Studio("Warner Bros.");
warners.addTag("Great Movies");
Studio marvel = new Studio("Marvel");
marvel.addTag("Great Movies");
entityManager.persist(warners);
entityManager.persist(marvel); // <-- ConstraintViolationException
...
}
Вышеприведенное приводит к исключению ConstraintViolationException, поскольку 2-й вызов entityManager.persist пытается снова сохранить тег.Если я пытаюсь изменить entityManager.persist на entityManager.merge, я получаю ту же проблему.Правильно ли я представляю эти отношения?Я ожидал, что hibernate проверит наличие тега, прежде чем пытаться вставить, а затем свяжет обе сущности в БД.
Таблицы определены следующим образом:
CREATE TABLE STUDIO (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
name varchar(255) not null,
description varchar,
master_id BIGINT REFERENCES STUDIO(id),
image_collection_id BIGINT REFERENCES IMAGE_COLLECTION(id)
);
CREATE TABLE ENTITY_TAG (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
tag varchar(255) not null UNIQUE
);
CREATE TABLE STUDIO_TAGS (
studio_id BIGINT REFERENCES STUDIO(id),
tags_id BIGINT REFERENCES ENTITY_TAG(id)
);
Спасибо за вашу помощь