我对一个要实现的“简单”案例感到非常疯狂
=> 我想删除通过多对一关系嵌套到父实体的子实体。
很简单不是吗?不幸的是不适合我:-(
下面是我的所有代码和我的尝试
第一个 => 父实体:
@Data
@NoArgsConstructor
@ToString(exclude = "books")
@Entity
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
@OneToMany(orphanRemoval = true, mappedBy = "category", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Book> books;
public Category(String name, Book... books) {
this.name = name;
this.books = Stream.of(books).collect(Collectors.toSet());
this.books.forEach(x -> x.setCategory(this));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Category)) return false;
Category category = (Category) o;
return Objects.equals(name, category.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
然后是子实体:
@Data
@RequiredArgsConstructor
@NoArgsConstructor
@ToString(exclude = "category")
@Entity
public class Book{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private @NonNull String name;
@ManyToOne(fetch = FetchType.EAGER)
private Category category;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Book)) return false;
Book book = (Book) o;
return Objects.equals(name, book.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
2 仓库
public interface BookRepository extends JpaRepository<Book, Integer> {
@Modifying
@Query("DELETE Book b WHERE b.category.id = ?1")
void deleteByCategoryId(int categoryId);
List<Book> findByCategoryId(int categoryId);
}
public interface CategoryRepository extends JpaRepository<Category, Integer> {
}
以及我正在使用的 Pom.xml 文件的摘录:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
令人惊讶的是,当我尝试删除父实体时,一切正常
int categoryId2 = categoryRepository.saveAndFlush(new Category("B", new Book("B1"), new Book("B2"))).getId();
Category category2 = categoryRepository.findById(categoryId2).get();
categoryRepository.delete(category2);
// Category and the 2 nested books have been removed from the DB
第一次尝试仅删除一本书,结果:
int categoryId = categoryRepository.saveAndFlush(new Category("A", new Book("A1"), new Book("A2"))).getId();
//Category and nested 2 books are perfectly persisted in DB
Category category = categoryRepository.findById(categoryId).get();
Book book = category.getBooks().iterator().next();
int bookId = book.getId();
category.getBooks().remove(book);
//to remove the link in the parent entity
book.setCategory(null);
//to remove the link in the child entity
categoryRepository.flush();
// to persist in the DB
// At this point, with the help of the orphanRemoval (true) property, i was expecting than the book would have been removed from the DB
// But nothing happened :-(
第二次尝试“疯狂的解决方法”
int categoryId = categoryRepository.saveAndFlush(new Category("A", new Book("A1"), new Book("A2"))).getId();
Category category = categoryRepository.findById(categoryId).get();
Book book = category.getBooks().iterator().next();
int bookId = book.getId();
category.getBooks().remove(book);
book.setCategory(null);
categoryRepository.flush();
//Same result as the first attempt, nothing happened in the DB
bookRepository.delete(book);
// with this delete call => the link was removed in the DB, book.category_id=null
bookRepository.delete(book);
// with this 2nd delete call => great result => the book entity was removed in the db
有人可以帮助我,给我一个好的方法吗?
最佳答案
试试这个
@OneToMany(orphanRemoval = true, mappedBy = "category", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private Set<Book> books;
请注意
级联 = CascadeType.PERSIST
希望能有所帮助。
Hibernate Tips: How to delete child entities from a many-to-one association
关于java - Spring 启动 JPA : How to delete child entity of a Many to One relation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60844427/