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_id
是 optional = 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();
}
}
我有两个实体:
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_id
是 optional = 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();
}
}