使用双向映射时未强制执行多列的@UniqueConstraint

时间:2017-11-15 15:46:58

标签: java hibernate jpa spring-data-jpa

我有这3个实体:

@Entity
class Resource {
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "resource", cascade = CascadeType.ALL, orphanRemoval = true)
    List<Element> elements;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "resource_id", nullable = false)
    List<Action> actions;
}

@Entity
@Table(name = "element", uniqueConstraints = @UniqueConstraint(name = "UK_ELEMENT_VALUE_FOR_RESOURCE", columnNames = { "value", "resource_id" }))
class Element {

    String value;

    @ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE })
    Resource resource;
}

@Entity
@Table(name = "action", uniqueConstraints = @UniqueConstraint(name = "UK_ACTION_VALUE_FOR_RESOURCE", columnNames = { "value", "resource_id" }))
class Action {

    String value;
    // no reference to Resource
}

我写了这两个测试:

当我持有具有相同值的2个操作的资源时,我向PersistenceException打招呼,其中包含休眠ConstraintViolationException作为预期的原因:

assertEquals(ConstraintViolationException.class, 
    assertThrows(PersistenceException.class, () -> {
        Resource res = newResource("res");
        res.setActions(Arrays.asList(new Action("value"), new Action("value")));
        dao.create(res);
    }).getCause().getClass());

当我持有具有相同值的2个元素的资源时,创建成功并且不会抛出异常。

assertEquals(ConstraintViolationException.class, 
    assertThrows(PersistenceException.class, () -> {
        Resource res = newResource("res");
        res.setElements(Arrays.asList(new Element("value"), new Element("value")));
        dao.create(res);
    }).getCause().getClass());

如果我用单向关系替换双向关系,我的测试工作。 我不需要Action的双向关系,但我需要在Element中。

我在那里做错了什么?我有点失落。

1 个答案:

答案 0 :(得分:0)

我通过称自己为Resource class中的双向设置器来实现它:

@PrePersist
void setBidirectionalMappingsOnPersist() {
    if (elements != null) {
        elements.forEach(element -> element.setResource(this));
    }
}

我在考虑在mappedBy中添加@OneToMany属性,持久性提供程序将处理双向映射。