gpt4 book ai didi

java - 传播级联删除引发外键约束失败

转载 作者:太空宇宙 更新时间:2023-11-04 09:37:11 25 4
gpt4 key购买 nike

我正在将 Spring Boot (2.1.0.RELEASE) 与 Spring Data JPA 结合使用。数据库是MySQL。

我在链式级联删除时遇到一些问题。

我有以下模型:

Database model

我不使用@ManyToMany,因为我需要在生成的表中添加其他字段,所以我的实体如下(无用的属性已被删除):

@Audited
@Entity
@Table(name = "request")
public class Request {

@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private Resource resource;

}


@Audited
@Entity
@Table(name = "resource")
public class Resource {

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "resource")
private Set<ResourceArticle> resourceArticles;

}

@Audited
@Entity
@Table(name = "resource_article")
public class ResourceArticle {

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "article_id")
private Article article;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "resource_id")
private Resource resource;

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "resourceArticle")
private Set<ResourceArticleOption> options;

}

@Audited
@Entity
@Table(name = "resource_article_option")
public class ResourceArticleOption {

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "option_id")
private Option option;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "resource_article_id")
private ResourceArticle resourceArticle;

}

然后,我只需从我的经理处发出扩展 CrudRepository 的请求 delete :

/* Repositroy */
public interface RequestRepository extends CrudRepository<Request, Long> {
}

/* Manager */
@Transactional
@Component("requestMgr")
public class RequestManager {

@Autowired
RequestRepository requestRepository;

public void delete(Request request) {
requestRepository.delete(request);
}

}

/* Viewmodel */
public class RequestVm {

@WireVariable
private RequestManager requestMgr;

public void deleteRequest(Request req) {
requestMgr.delete(req);
}

}

错误是:

Caused by: java.sql.SQLException: Cannot delete or update a parent row: a foreign key constraint fails (my_db.resource_article, CONSTRAINT FK5wqvprkwx05fb5hgt6w9h7nbk FOREIGN KEY (resource_id) REFERENCES resource (id))

启用跟踪时的输出:

delete from request where id=?
binding parameter [1] as [BIGINT] - [24]
delete from resource where id=?
binding parameter [1] as [BIGINT] - [71]
SQL Error: 1451, SQLState: 23000
(conn=30) Cannot delete or update a parent row: a foreign key constraint fails (`my_db`.`resource_article`, CONSTRAINT `FK5wqvprkwx05fb5hgt6w9h7nbk` FOREIGN KEY (`resource_id`) REFERENCES `resource` (`id`))

奇怪的是,它尝试按照 request > resource > resource_article > resource_article_option 的顺序删除?

需要 CascadeType.ALL,因为我想持久和删除。

我可以通过在删除之前设置对 null 的引用来打破链条,但这当然会导致数据库中出现孤立记录。

这里最好的策略是什么?

最佳答案

我通过在每个关系中删除不是该关系所有者的实体来使其发挥作用。

@ManyToMany 关系中的级联删除不仅应用于链接表,还应用于关系的另一端。

@ManyToMany 关联中删除时这是一个众所周知的问题(例如,here 对此有很好的解释),但我没有注意,因为我的注释不是直接的 @ManyToMany 而是双重 @OneToMany 关联,而且我认为 JPA 会像简单的 @OneToMany 关系一样级联删除,但看来我错了。

我在删除请求之前使用了@preRemove 来清理关系:

ResourceArticle中:

@PreRemove
public void preRemove() {
article.getResourceArticles().remove(this);
}

ResourceArticleOption中:

@PreRemove
public void preRemove() {
option.getResourceArticleOptions().remove(this);
}

然后一切就都完美了。

关于java - 传播级联删除引发外键约束失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56363413/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com