Spring 本机查询中的 JPA 存储库子查询
Spring JPA Repository Sub-Query In Native Query
我正在尝试 运行 存储库方法的本机查询,以便它 return 对结果进行一些计数。使用 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
注释的属性,因此信息不会持久保存到数据库中。除了 2 个 t运行sient 属性外,所有数据都正常返回,这些属性 return 为空值。当我从控制台复制查询并将其粘贴到 MySQL Workbench 时,结果符合预期并且我看到了我需要的计数。无论如何,不确定是否还需要做任何其他事情才能使此本机查询用作注释。我在子查询 SELECT 55 FROM...
中硬编码了一个值,只是为了查看计数是否有问题,但它仍然 return 为 null。我 运行 Workbench 中的查询,它工作正常。
我尝试将 Integer, Long, BigInteger, long, int...
和 none 中的 t运行sient 属性 类型更改为不同。由于我使用的是 Groovy,因此我还尝试 def
让 Groovy 推断类型,但这也没有用。
我也尝试从终端 运行ning 项目,但仍然无法正常工作。我已经在 Mac 和 Linux 上试过了,但没有成功显示计数结果。
这行不通。您可以使用 SQLConstructorExpression
,但返回的实例将不受管理,这是一个主要缺点。
更好的选择是创建一个简单的数据库视图,其中包含项目的摘要信息。您可以使用 JPA 的 @SecondaryTable
功能将项目实体映射到它的 table 和关联的摘要视图。
另一个好处是您可以像对任何其他 属性.
一样对汇总值进行排序和查询
更新映射:
@Entity
@Table(name = "projects")
@SecondaryTable(name = "projects_summary_vw")
public class Project{
//use Integer rather than int to avoid issue outlined here:
//
@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 {
}
另一种 non-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
}
我正在尝试 运行 存储库方法的本机查询,以便它 return 对结果进行一些计数。使用 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
注释的属性,因此信息不会持久保存到数据库中。除了 2 个 t运行sient 属性外,所有数据都正常返回,这些属性 return 为空值。当我从控制台复制查询并将其粘贴到 MySQL Workbench 时,结果符合预期并且我看到了我需要的计数。无论如何,不确定是否还需要做任何其他事情才能使此本机查询用作注释。我在子查询 SELECT 55 FROM...
中硬编码了一个值,只是为了查看计数是否有问题,但它仍然 return 为 null。我 运行 Workbench 中的查询,它工作正常。
我尝试将 Integer, Long, BigInteger, long, int...
和 none 中的 t运行sient 属性 类型更改为不同。由于我使用的是 Groovy,因此我还尝试 def
让 Groovy 推断类型,但这也没有用。
我也尝试从终端 运行ning 项目,但仍然无法正常工作。我已经在 Mac 和 Linux 上试过了,但没有成功显示计数结果。
这行不通。您可以使用 SQLConstructorExpression
,但返回的实例将不受管理,这是一个主要缺点。
更好的选择是创建一个简单的数据库视图,其中包含项目的摘要信息。您可以使用 JPA 的 @SecondaryTable
功能将项目实体映射到它的 table 和关联的摘要视图。
另一个好处是您可以像对任何其他 属性.
一样对汇总值进行排序和查询更新映射:
@Entity
@Table(name = "projects")
@SecondaryTable(name = "projects_summary_vw")
public class Project{
//use Integer rather than int to avoid issue outlined here:
//
@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 {
}
另一种 non-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
}