我正在尝试对存储库方法运行本机查询,以便它返回带有一些计数的结果。使用JPQL太复杂了,所以我选择了原生查询。
存储库
@RepositoryRestResource(collectionResourceRel="projects", path="projects")
interface ProjectRepository extends BaseRepository<Project, Long>, ProjectRepositoryCustom {
@Query(
value="SELECT p.id, p.user_id, p.title, p.description, p.created_on, p.version,(SELECT COUNT(0) FROM projectparts WHERE project_id = p.id) AS parts,(SELECT COUNT(0) FROM requests WHERE project_id = p.id) AS requests FROM projects AS p ORDER BY ?#{#pageable}",
countQuery="SELECT COUNT(0) FROM projects",
nativeQuery=true
)
Page<Project> findAll(Pageable pageable)
}
实体有2个用@Transient
注释的属性,因此信息不会持久保存到数据库中。除了为值返回null的2个瞬态属性外,所有数据都返回正常。当我从控制台复制查询并将其粘贴到MySQL Workbench中时,结果是预期的,我看到了我需要的计数。无论如何,不确定是否还有其他事情需要完成才能使这个本机查询作为注释工作。我在子查询SELECT 55 FROM...
中硬编码了一个值,只是为了查看它是否是计数的问题,它仍然返回为null。我在Workbench中运行了查询,它运行正常。
我已尝试从Integer, Long, BigInteger, long, int...
更改瞬态属性类型,但这些都没有任何区别。由于我使用的是Groovy,我还尝试def
让Groovy推断出类型,但也没有。
我也试过从终端运行项目,但它仍然无法正常工作。我已经在Mac和Linux上尝试过了,并且没有显示计数结果的运气。
答案 0 :(得分:2)
这不起作用。您可以使用SQLConstructorExpression
但是返回的实例将是不受管理的,这是一个主要缺点。
更好的选择是创建一个简单的数据库视图,其中包含项目的摘要信息。您可以使用JPA的@SecondaryTable
功能将Project实体映射到它的表和关联的摘要视图。
另一个好处是,您可以对任何其他属性进行排序和查询汇总值。
更新了地图:
@Entity
@Table(name = "projects")
@SecondaryTable(name = "projects_summary_vw")
public class Project{
//use Integer rather than int to avoid issue outlined here:
//http://stackoverflow.com/a/37160701/1356423
@Column(name = "parts", table = "projects_summary_vw",
insertable="false", updateable="false")
private Integer partsCount;
@Column(name = "requests", table = "requestsCount"
insertable="false", updateable="false")
private Integer requestsCount;
//other mappings as required
}
无需自定义查询:
@RepositoryRestResource(collectionResourceRel="projects",
path="projects")
interface ProjectRepository extends BaseRepository<Project, Long>,
ProjectRepositoryCustom {
}
替代的非JPA兼容解决方案可能是使用某些特定于供应商的扩展而不是视图。例如,Hibernate有一个@Formula
注释可以使用:
https://docs.jboss.org/hibernate/orm/5.1/javadocs/org/hibernate/annotations/Formula.html
@Entity
@Table(name = "projects")
public class Project{
@Formula("my count query as native sql")
private Integer partsCount;
@Formula("my count query as native sql")
private Integer requestsCount;
//other mappings as required
}