如何在 Spring Data JPA 中使用带分页的投影接口?
How to use projection interfaces with pagination in Spring Data JPA?
我正在尝试使用 spring 数据 projections
的新功能获取部分实体 (NetworkSimple) 的页面
我已经检查了文档,如果我只要求:
Collection<NetworkSimple> findAllProjectedBy();
有效,但如果我使用可分页:
Page<NetworkSimple> findAllProjectedBy(Pageable pageable);
它抛出一个错误:
org.hibernate.jpa.criteria.expression.function.AggregationFunction$COUNT cannot be cast to org.hibernate.jpa.criteria.expression.CompoundSelectionImpl
有人已经使用过这个吗?
我的 NetworkSimple class 如下:
public interface NetworkSimple {
Long getId();
String getNetworkName();
Boolean getIsActive();
}
问题可能出在方法名上。 by 关键字表示您通过特定 属性 过滤数据:例如 findByName。它从方法名称调用查询创建:
所以试试 Page<NetworkSimple> findAll(Pageable pageable);
注意: 此功能应该按照原始发帖人描述的方式工作,但由于 this bug 它没有。该错误已针对 Hopper SR2 版本修复,如果您停留在早期版本上,则以下解决方法将起作用。
可以将 Pageable
与 Spring Data JPA 1.10 (Hopper) 中引入的新查询投影功能一起使用。您将需要使用 @Query
注释并手动为您需要的字段编写查询,它们还必须使用 AS
别名以允许 Spring 数据确定如何投影结果. spring 引导存储库的 spring-boot-samples 部分有一个很好的示例。
在你的例子中它会很简单:
@Query("SELECT n.id AS id, n.name AS networkName, n.active AS isActive FROM Network n")
Page<NetworkSimple> findAllProjectedBy(Pageable pageable);
我假设您的实体看起来像这样:
@Entity
public class Network
{
@Id
@GeneratedValue
private Long id;
@Column
private String name;
@Column
private boolean active;
...
}
Spring数据会自动为分页信息导出计数查询。也可以在查询中使用连接来获取关联,然后在投影中汇总它们。
我认为您需要创建 findAllProjectedBy()
作为 specification.Then 您可以使用这样的 findAll()
方法。
示例:findAll(findAllProjectedBy(),pageable)
关注 link 可能有助于找到如何在 spring 中创建规范。
https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
您可以使用:
@Query("SELECT n FROM Network n")
Page<? extends NetworkSimple> findAllProjectedBy(Pageable pageable);
即使使用 spring-data-jpa 1.11.4,类似
public interface NetworkRepository extends JpaRepository<Network, String> {
Page<NetworkSimple> findAll(Pageable pageable);
}
不会编译;报告
findAll(org.springframework.data.domain.Pageable) in NetworkRepository clashes with findAll(org.springframework.data.domain.Pageable) in org.springframework.data.repository.PagingAndSortingRepository
return type org.springframework.data.domain.Page<NetworkSimple> is not compatible with org.springframework.data.domain.Page<Network>
我们找到的解决方法是将 findAll 重命名为 findAllBy,例如
public interface NetworkRepository extends JpaRepository<Network, String> {
Page<NetworkSimple> findAllBy(Pageable pageable);
}
您可以像这样将界面投影与 Pageable 一起使用:
Page<NetworkSimple> findPagedProjectedBy(Pageable pageable);
带有一些参数:
Page<NetworkSimple> findPagedProjectedByName(String name, Pageable pageable);
我正在尝试使用 spring 数据 projections
的新功能获取部分实体 (NetworkSimple) 的页面我已经检查了文档,如果我只要求:
Collection<NetworkSimple> findAllProjectedBy();
有效,但如果我使用可分页:
Page<NetworkSimple> findAllProjectedBy(Pageable pageable);
它抛出一个错误:
org.hibernate.jpa.criteria.expression.function.AggregationFunction$COUNT cannot be cast to org.hibernate.jpa.criteria.expression.CompoundSelectionImpl
有人已经使用过这个吗?
我的 NetworkSimple class 如下:
public interface NetworkSimple {
Long getId();
String getNetworkName();
Boolean getIsActive();
}
问题可能出在方法名上。 by 关键字表示您通过特定 属性 过滤数据:例如 findByName。它从方法名称调用查询创建:
所以试试 Page<NetworkSimple> findAll(Pageable pageable);
注意: 此功能应该按照原始发帖人描述的方式工作,但由于 this bug 它没有。该错误已针对 Hopper SR2 版本修复,如果您停留在早期版本上,则以下解决方法将起作用。
可以将 Pageable
与 Spring Data JPA 1.10 (Hopper) 中引入的新查询投影功能一起使用。您将需要使用 @Query
注释并手动为您需要的字段编写查询,它们还必须使用 AS
别名以允许 Spring 数据确定如何投影结果. spring 引导存储库的 spring-boot-samples 部分有一个很好的示例。
在你的例子中它会很简单:
@Query("SELECT n.id AS id, n.name AS networkName, n.active AS isActive FROM Network n")
Page<NetworkSimple> findAllProjectedBy(Pageable pageable);
我假设您的实体看起来像这样:
@Entity
public class Network
{
@Id
@GeneratedValue
private Long id;
@Column
private String name;
@Column
private boolean active;
...
}
Spring数据会自动为分页信息导出计数查询。也可以在查询中使用连接来获取关联,然后在投影中汇总它们。
我认为您需要创建 findAllProjectedBy()
作为 specification.Then 您可以使用这样的 findAll()
方法。
示例:findAll(findAllProjectedBy(),pageable)
关注 link 可能有助于找到如何在 spring 中创建规范。
https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
您可以使用:
@Query("SELECT n FROM Network n")
Page<? extends NetworkSimple> findAllProjectedBy(Pageable pageable);
即使使用 spring-data-jpa 1.11.4,类似
public interface NetworkRepository extends JpaRepository<Network, String> {
Page<NetworkSimple> findAll(Pageable pageable);
}
不会编译;报告
findAll(org.springframework.data.domain.Pageable) in NetworkRepository clashes with findAll(org.springframework.data.domain.Pageable) in org.springframework.data.repository.PagingAndSortingRepository
return type org.springframework.data.domain.Page<NetworkSimple> is not compatible with org.springframework.data.domain.Page<Network>
我们找到的解决方法是将 findAll 重命名为 findAllBy,例如
public interface NetworkRepository extends JpaRepository<Network, String> {
Page<NetworkSimple> findAllBy(Pageable pageable);
}
您可以像这样将界面投影与 Pageable 一起使用:
Page<NetworkSimple> findPagedProjectedBy(Pageable pageable);
带有一些参数:
Page<NetworkSimple> findPagedProjectedByName(String name, Pageable pageable);