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

Spring JPA: Prevent deleting if relations still exist

我有两个实体:

Table activity:

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

Class:

@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;
}

和table 里程碑

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

Class:

@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 时,我的 Activity 会保持完整。但是,milestone_id 仍然指向已删除的相关里程碑。

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

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

我觉得合乎逻辑。

但是我想要的是 Milestone 不能被删除,因为 activity table 上的 milestone_idoptional = false

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

您的问题与您的数据库模式有关 - 我试过 reproducing your problem 并且我确定您没有使用应用程序生成的模式,但是已经存在一个 没有定义外键。请参阅出现 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();
    }
}