Spring JPA:如果关系仍然存在,则禁止删除

时间:2016-02-10 10:25:03

标签: java spring hibernate jpa cascade

我有两个实体:

活动

|id|milestone_id|..|
| 1|3           |..|
| 2|3           |..|

类别:

@Entity
@Table(name="activity")
public class Activity implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    @ManyToOne(optional = false)
    private Milestone milestone;
}

和表里程碑

|id|..|
| 3|..|

类别:

@Entity
@Table(name="milestone")
public class Milestone implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @Column(nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    @JsonIgnore
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "milestone")
    private List<Activity> activities = new ArrayList<>();
}

现在,当我删除里程碑3时,我的活动保持不变。但是,milestone_id仍指向已删除的相关里程碑。

现在,当我再次检索活动时,我收到此错误:

javax.persistence.EntityNotFoundException: Unable to find nl.geodan.vergunningen.manager.domain.Milestone with id 3

对我来说似乎很合乎逻辑。

但我想要的是,里程碑无法删除,因为活动表上的milestone_idoptional = false

我错过了什么? 我应该重新加载活动吗?我应该使用某种CascadeType吗?

1 个答案:

答案 0 :(得分:2)

您的问题与您的数据库架构有关 - 我已尝试reproducing your problem并且我确定您没有使用应用程序生成的架构,但已经存在一个没有定义外键< / strong>即可。请参阅发生ConstraintViolationException的output.txt文件。

您可以通过执行正确的SQL命令将外键添加到数据库中:

ALTER TABLE Activity
ADD FOREIGN KEY (milestone_id)
REFERENCES Milestone(id)

或者只是将spring.jpa.hibernate.ddl-auto属性(in case of spring boot)更改为create。如果您使用原始Spring,那么它将属于Hibernate本身的属性 - hibernate.hbm2ddl.auto=create

如果您没有对架构的访问权限或权限,您可以通过编程方式处理它,但这肯定是解决方法,只是闻起来很糟糕 - 一个解决方案是每次删除Milestone实体时检查依赖关系,另一个涉及将@PreDelete监听器放入Milestone实体:

@PreRemove
private void preRemove() {
    if (!activities.isEmpty()) {
        throw new LinkedActivityExistsException();
    }
}