I'm using Spring Boot (2.1.0.RELEASE) with Spring Data JPA. Database is MySQL.
I have some problem to chain cascade delete.
I have the following model :
I do not use @ManyToMany
because I need additional fields in generated tables, so my entities are as follow (useless properties have been removed) :
@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;
}
Then from my manager I simply issue the request delete
extending 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);
}
}
Error is :
Caused by: java.sql.SQLException: Cannot delete or update a parent row: a foreign key constraint fails (
my_db
.resource_article
, CONSTRAINTFK5wqvprkwx05fb5hgt6w9h7nbk
FOREIGN KEY (resource_id
) REFERENCESresource
(id
))
The output when enabling tracing :
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`))
Strange that it tries to delete in the order request
> resource
> resource_article
> resource_article_option
?
I need CascadeType.ALL
as I want to PERSIST and DELETE.
I can break the chain by setting reference to null
before deleting but of course it results in orphan records in the database.
What is the best strategy here ?