java 为什么@OneToMany关系会生成额外的SQL选择查询?

63lcw9qa  于 2023-02-02  发布在  Java
关注(0)|答案(2)|浏览(199)
@Entity
public class Author  {
    @OneToMany(cascade = {PERSISTE, MERGE},
            mappedBy = "author")
    private List<Book> books = new ArrayList<>();
    
    public void addBook(Book book) {
        this.books.add(book);
        book.setAuthor(this);
    }
    
    //other fields
    
}
    
@Entity
public class Book{

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "author_id")
    private Author author;
}

public class BookService {

    AuthorRepository repository;

    @Transactional
    public void saveBooks(){

    Book newBook = new Book);
    
    Author author = repository.findByid(1L);
    author.addBook(newBook);
    }
}

在数据库中,作者已经包含一本书。我为作者创建了一本新书,并希望保存它。
但是当调用函数addBook时,现有的图书将从数据库加载。我在日志中看到了额外的SQL查询:@Query[“选择图书...."]
我该如何解决这个问题?我不希望有额外的SQL选择

nwo49xxi

nwo49xxi1#

这就是PersistentBag的工作原理--当你在列表上执行操作时,Hibernate会加载它。我只需要简单地将添加新书替换为将创建的书引用到现有的Author

public class BookService {

    BookRepository bookRepository;
    AuthorRepository authorRepository;

    @Transactional
    public void saveBooks() {

        Book newBook = new Book();

        Author author = authorRepository.findByid(1L);
        newBook.setAuthor(author);
        bookRepository.save(newBook);
    }
}
yk9xbfzb

yk9xbfzb2#

其原因是JPA工作的基本前提:加载对象图,操作对象图,在事务结束时,JPA确保更改在数据库中结束。
我认为有两种方法可以避免选择。
1.颠倒关系:当Book引用Author时,不需要加载集合,因为它根本不存在,如果你真的需要这个集合,你可以使用一个专门的查询。
1.回到SQL,只执行一个SQL插入语句。当然,这可能会导致数据库和JPA的一级缓存之间的不一致。请确保您了解一级缓存的工作原理及其用途。

相关问题