Я использую 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
))
Вывод при включении трассировки:
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
?
I нужно CascadeType.ALL
, поскольку я хочу PERSIST и DELETE.
Я могу разорвать цепочку, установив ссылку на null
перед удалением, но, конечно, это приведет к появлению в базе данных потерянных записей.
Какова лучшая стратегия здесь?