【问题标题】:Spring JPA - Delete Child in One-toMany relationshipSpring JPA - 删除一对多关系中的子级
【发布时间】:2016-03-05 12:12:51
【问题描述】:

我有以下 Author 类:

@Entity
public class Author  implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private Long id;

    @OneToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
    @JoinTable(
        name="author_book",
        joinColumns = @JoinColumn( name="author_id"),
        inverseJoinColumns = @JoinColumn( name="book_id")
    )
    private Set<Book> books= new HashSet<Book>();

    public Author() {
        super();
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Set<Book> getBooks() {
       return books;
    }

    public void setBooks(Set<Book> books) {
        this.books = books;
    }
 }

我还有以下图书实体:

@Entity
public class Book implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private Long id;

    public Book() {
        super();
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

}

接下来,我有以下两个仓库:

public interface BookRepository extends CrudRepository<Book, Long> {
}
public interface AuthorRepository extends CrudRepository<Author, Long>{
}

最后,我有以下测试用例:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class AuthorRepositoryIntegrationTests {

    @Autowired
    AuthorRepository authorRepository;
    @Autowired
    BookRepository bookRepository;

    @Test
    @Transactional
    public void deleteBookFromAuthor() {
        Book book= new Book();
        Author author= new Author();
        author.getBooks().add(book);
        author=this.authorRepository.save(author);

        Iterable<Author> authors = this.authorRepository.findAll();
        author=authors.iterator().next();
        book=author.getBooks().iterator().next();
        this.bookRepository.delete(book);

        authors = this.authorRepository.findAll();
        assertEquals(authors.iterator().next().getBooks().size(),0);
    }
}

我的问题是这个测试用例中的最后一个断言失败了。如果我向作者添加一本书,它会自动添加到图书存储库中。但是,如果我从存储库中删除一本书,我如何从作者那里删除它?

【问题讨论】:

    标签: hibernate jpa spring-data spring-data-jpa


    【解决方案1】:

    REDO:好的,抱歉,我没有仔细看你的问题。答案虽然很简单,但这次我真的试过了。您需要从 POJO 中的父级中删除子级并重新保存没有子级的父级。请参阅下面的注释代码:

    List<Book> books = new ArrayList<Book>();
    
    Book book = new Book();
    books.add(book);
    
    Author author = new Author();
    author.setBooks(books);
    authorRepository.save(author);
    
    Author a =authorRepository.findAll().iterator().next();
    Book b = a.getBooks().get(0);
    bookRepository.delete(b);
    
    // REMOVE FROM PARENT
    a.getBooks().remove(0);
    authorRepository.save(a);
    
    a = authorRepository.findAll().iterator().next();
    System.out.println(a);
    

    编辑:如果您担心一致性,您应该这样做,只需从作者 POJO 中删除该书,当您保存作者时,cascade=CascadeType.ALL 将为您传播删除该书。例如:

    Author a =authorRepository.findAll().iterator().next();
    a.getBooks().remove(0);
    authorRepository.save(a);
    
    // NO BOOK
    a = authorRepository.findAll().iterator().next();
    System.out.println(a);
    

    【讨论】:

    • 感谢您的意见。它没有这样做。我在最后一个 findAll() 之前添加了 getTransaction() 和 commit()。仍然得到 getBooks().size()==1。
    • 好的。因此,您从 bookRepository 中删除并从集合中删除。我担心确实必须在两个地方删除。因为如果我只在 bookRepository 中删除,它会使我的数据库不一致,因为作者将引用不存在的书籍。我的猜测是有某种注释组合可以让我防止这种情况发生吗?
    • 更简单,只需使用 POJO 并让 cascade 完成它的工作。请参阅编辑,如果有帮助请接受。
    • 我找不到让它双向工作的方法。所以我最终采用了级联方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-12
    • 2015-03-24
    • 2021-02-05
    • 2021-07-12
    • 1970-01-01
    • 2023-01-16
    • 1970-01-01
    相关资源
    最近更新 更多