我正在将Spring Boot(2.1.0.RELEASE)与Spring Data JPA一起使用。数据库是MySQL。
链式级联删除时遇到一些问题。
我有以下模型:
我不使用@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;
}
然后从我的经理那里,我发出扩展delete
的请求CrudRepository
:
/* 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);
}
}
错误是:
由于:java.sql.SQLException:无法删除或更新父级 行:外键约束失败 ({
my_db
。resource_article
,约束FK5wqvprkwx05fb5hgt6w9h7nbk
外键(resource_id
)参考resource
(id
))
启用跟踪时的输出:
binding parameter [1] as [BIGINT] - [1]
delete from resource where id=?
binding parameter [1] as [BIGINT] - [1]
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`))
我需要CascadeType.ALL
才能持久和删除。
我可以通过在删除前将引用设置为null来打破链条,但这会导致数据库中的孤立记录。
这里最好的策略是什么?
答案 0 :(得分:0)
我通过在每个关系中删除非关系所有者的实体来使其正常工作。
@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);
}
然后一切正常。