我有两个班级,一对一。 User
:
@Entity
public class User {
@Id
private Long id;
...
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private Set<Note> notes = new HashSet<>();
...
}
和Note
:
@Entity
public class Note {
@Id
private Long id;
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
...
}
在UserRepository
中,我想从findAll(Pageable<T> va1)
覆盖PagingAndSortingRepository<T, ID>
方法,以避免N + 1查询问题。使用以下代码,一切正常:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Override
@Query(value = "select distinct u from User u left join fetch u.notes")
Page<User> findAll();
}
但是当我添加分页时:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Override
@Query(value = "select distinct u from User u left join fetch u.notes",
countQuery = "select count(u) from User u")
Page<User> findAll(Pageable page);
}
我在控制台中看到警告:
HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!
我的问题是,如何解决?
答案 0 :(得分:1)
当您希望join fetch
进行分页时,Hibernate进行不分页的SQL查询意味着获取完整的结果集。并在内存中进行分页。
使用两个查询解决此问题的简便方法
代码示例
@Query("select u.id from User u")
List<Long> getAllIds(Pageable page);
@Query(value = "select distinct u from User u left join fetch u.notes where u.id IN (:ids)")
List<User> findAll(@Param("ids")List<Long> ids);
答案 1 :(得分:1)
这是Blaze-Persistence的完美用例。
Blaze-Persistence是JPA之上的查询构建器,它支持JPA模型之上的许多高级DBMS功能。随附的分页支持可解决您可能遇到的所有问题。
它还具有Spring Data集成,因此您可以像现在一样使用相同的代码,只需添加依赖项并进行设置:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-setup
Blaze-Persistence具有许多可以配置的分页策略。默认策略是将ID查询内联到主查询中。像这样:
select u
from User u
left join fetch u.notes
where u.id IN (
select u2.id
from User u2
order by ...
limit ...
)
order by ...