Я схожу с ума от этого ... Я следил за всеми статьями от Мысли о Java и Владом Михалчеа об отображении ассоциаций в hibernate, но я не знаю, почему удаление в @ManyToMany, так или иначе, всегда запутано в моем проектеоб услугах отдыха с Spring Data Jpa.
У меня есть базовая книга -> авторы многих отношений, которые, как мне кажется, я правильно отобразил (по крайней мере, в соответствии с тем, как они рекомендуют в двух ссылках, приведенных выше).
Я перезаписываю equals и hashcode, я написал и использую методы для управления связями между сущностями, но когда я пытаюсь удалить книги из авторов (которые я хочу удалить), я получил ConcurrentModificationException: null, даже если яиспользуйте итератор.
Мои объекты:
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
@Size( min = 2, max = 30)
@Column (length = 30)
private String firstName;
@Size( min = 2, max = 30)
@Column (length = 30)
private String lastName;
@ManyToMany(mappedBy = "authors")
private Set<Book> books = new HashSet<>();
public Author(@NotNull @Size(min = 2, max = 30) String firstName, @NotNull @Size(min = 2, max = 30) String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public void addBook(Book book){
this.books.add(book);
book.getAuthors().add(this);
}
public void removeBook(Book book){
this.books.remove(book);
book.getAuthors().remove(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (this.getClass() != o.getClass()) return false;
return id != null && id.equals(((Author)o).getId());
}
@Override
public int hashCode() {
return 17;
}
}
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String isbn;
@NotNull
private String title;
//Owning side
@NotNull
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "book_author",
joinColumns = @JoinColumn(name = "book_id"),
inverseJoinColumns = @JoinColumn(name = "author_id"))
private Set<Author> authors = new HashSet<>();
public Book(String title) {
this.title = title;
this.isbn = RandomStringUtils.randomAlphanumeric(10);
}
public void addAuthor(Author author){
this.authors.add(author);
author.getBooks().add(this);
}
public void removeAuthor(Author author){
this.authors.remove(author);
author.getBooks().remove(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (this.getClass() != o.getClass()) return false;
return id != null && id.equals(((Book)o).getId());
}
@Override
public int hashCode() {
return 13;
}
}
Мой метод удаления, который находится на моем бизнес-уровне:
public void deleteAuthor(Long id) {
Optional<Author> author = authorRepository.findById(id);
if (author.isPresent()){
Author au = author.get();
for (Book book : au.getBooks()) {
au.removeBook(book);
}
authorRepository.delete(au);
}
}
У меня есть исключение после первого цикла вдля каждого. Это написано точно так же, как в примерах, поэтому я понятия не имею. Интересно, что делает Spring Data Layer более сложным? Спасибо за вашу помощь!
РЕДАКТИРОВАТЬ: Исключение появляется только в том случае, если мой автор владеет более чем одной книгой