【问题标题】:Querying in One to many mappings in hibernate在休眠中查询一对多映射
【发布时间】:2020-08-10 10:59:19
【问题描述】:

假设我有一个书实体和一个图书馆实体(一个图书馆可以有多本书,但每本书只属于一个图书馆)。它们的定义如下:

public class Library
{
    @Id
    private Long id;

    @OneToMany(mappedBy = "library")
    private List<Book> books = new ArrayList<>();
}

public class Book
{
    @Id
    private Long id;

    @ManyToOne
    @JoinColumn(name="FK_Library", nullable=false)
    private Library library;
}

我想查找属于特定图书馆的所有书籍。一种方法是创建一个LibraryRepository,如下所示:

public interface LibraryRepository extends JpaRepository<Library, Long>{}

现在我有 findById(Long libraryId) 方法,它返回一个带有 List&lt;Book&gt;Library 对象。

我想知道是否可以创建一个BookRepository 并声明一个名为findByLibraryId(Long libraryId) 的方法并让hibernate 通过外键FK_Library 查询Book 表,不执行任何连接强>。

类似这样的:

public interface BookRepository extends JpaRepository<Book, Long> {
    public List<Book> findByLibraryId(Long libraryId);
}

上面的方法findByLibraryId确实执行了join。我不希望它执行连接,因为我只想找到所有具有由外键关系定义的library_id 的行。

第一种方法比第二种方法更可取吗?

【问题讨论】:

  • 为什么你需要这个?您可以使用本机查询执行此操作,也可能使用 JPQL
  • 使用本机查询可能会将其绑定到特定类型的架构。
  • 另外,在LibraryRepositoryfindById 方法中,它返回Library 对象和List&lt;Book&gt;,但是当我看到休眠生成的查询时它不执行连接。这怎么可能?
  • @OneToMany 默认是惰性的,所以首先获取图书馆,然后在调用 getter 时在单独的查询中获取图书馆的书籍。所以执行了 2 个查询。

标签: java hibernate jpa spring-data-jpa


【解决方案1】:

您可以使用 @Query 和 JPQL 来做到这一点

@Query("SELECT b FROM Book b WHERE b.library.id = :libraryId")
public List<Book> findByLibraryId(Long libraryId);

【讨论】:

  • 从性能方面看,使用@Query更好还是使用LibraryRepository的findById方法?
  • 取决于你是否只想要图书馆的书然后使用@Query,如果你想要图书馆也可以在LibraryRepository 中查询,而不是使用@EntityGraph 使用一个查询进行两次查询
【解决方案2】:

您可以将 @ManyToOne 关系更改为延迟加载。

@ManyToOne(fetch = FetchType.LAZY)

这是 OneToMany 的默认设置,这就是为什么您在搜索库时看不到加入。

【讨论】:

    猜你喜欢
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 2019-02-19
    • 1970-01-01
    相关资源
    最近更新 更多