考虑两个实体Thread和User,每个线程都属于一个用户,ThreadRepository
中有两个方法:
@Repository
public interface ThreadRepository extends JpaRepository<Thread, Long> {
@EntityGraph(type = EntityGraph.EntityGraphType.FETCH, attributePaths = {"user"})
Page<Thread> findAllByOrderByCreatedDateDesc(Pageable pageable);
@Query(value = "SELECT T.*, U.* FROM THREAD T LEFT JOIN FRM_USER U ON U.id = T.USER",
countQuery = "SELECT COUNT(T.ID) FROM THREAD T",
nativeQuery = true)
Page<Thread> findAllCustomMethod(Pageable pageable);
}
字符串
我可以使用@EntityGraph
处理findAllByOrderByCreatedDateDesc
方法的 *n + 1个查询问题 *。
我的问题是,对于包含nativeQuery
的findAllCustomMethod
方法,解决这个问题的最佳解决方案是什么?
1条答案
按热度按时间ymdaylpp1#
LEFT JOIN FRM_USER
在这种情况下没有使用,Spring Data JPA只会将T.*
字段Map到Thread
,忽略U.*
字段。相反,它会导致重复!
JPA实现将延迟选择User示例,从而导致N+1问题。
你不能使用投影,因为“基于类的投影根本不适用于本机查询”。
在这种情况下,nativeQuery没有JPQL查询的好处,在JPQL查询中,您可以使用LEFT JOIN FETCH来急切地获取User示例并避免N+1。
Spring Data在这里没有帮助。
如果您确实需要SQL查询,可以使用SqlResultSetMapping。
当使用SQL查询(又名. native queries)时,您可以从Spring的
JdbcTemplate.query
方法中受益,该方法具有自定义ResultSetExtractor
,该方法将使用自定义实现构建您的Object。使用ResultSetExtractor
实现这种精确情况的解决方案非常简单,但分页部分将非常冗长。字符串