Как применить уникальное ограничение для @OneToMany - PullRequest
0 голосов
/ 16 апреля 2019

У меня есть отношение @ 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)
);

Спасибо за вашу помощь

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