使用JPA/QueryDSL的类似Pivot的结果

swi*_*ler 8 java sql pivot jpa querydsl

我们在项目中使用JPA2,Spring Data和QueryDSL.我有以下表格和相关的JPA实体:

table Person (id, ...) 

table Activity (id, type, ...)

@Entity
@Configurable
public class Activity {
   @ElementCollection
   @CollectionTable(joinColumns = @JoinColumn(name = "ACTIVITY_ID"))
   @NotEmpty
   @Valid
   private Set<ActivityName> names = new HashSet<>();

table ActivityName(activity_id, name, ...) 

@Embeddable
  @Immutable
  @Table(uniqueConstraints = @UniqueConstraint(columnNames = "NAME"))
  public static class ActivityName { ... }

table ActivityLevel(person_id, activity_id, level) 

@Entity
@Immutable
@Validated
public final class ActivityLevel{...}
Run Code Online (Sandbox Code Playgroud)

1..n for Actitivy to ActivityName - 活动可能有不同的名称(例如跑步,慢跑)

一个人可能对某个特定活动具有一定的水平,并且可以执行多个活动(每个活动都有一个定义的级别).

  • 应该搜索活动名称(例如跑步等)作为参数(活动名称列表)
  • 因此,应该找到执行相关活动的所有人员.
  • 结果应包含搜索所有活动的相应级别,人员姓名和人员活动的总和

示例以下数据:

  • Person =(id = 1,name = Bob)
  • Person =(id = 2,name = Mary)
  • 活动=(1,...)
  • 活动=(2,...)
  • ActivityName =(activity_id = 1,name ="jogging")
  • ActivityName =(activity_id = 1,name ="running")
  • ActivityName =(activity_id = 2,name ="dancing")
  • ActivityLevel =(person_id = 1,activity_id = 1,level = 0.7f)
  • ActivityLevel =(person_id = 1,activity_id = 2,level = 0.1f)
  • ActivityLevel =(person_id = 2,activity_id = 1,level = 0.5f)

搜索"跑步"或"跳舞"的人应该得到这样的结果:

Person[Name]   ActitiyName  ActivityLevel ActitiyName  ActivityLevel  Sum
Bob             running         0.7         dancing         0.1       0.8
Mary            running         0.5                                   0.5          
Run Code Online (Sandbox Code Playgroud)

我的问题:是否有JPA QL/QueryDSL方法通过一个表达式/投影得到这样的结果?我已经拥有的是一个多步骤的解决方案 - 选择活动名称和级别,执行分组并与Java8求和.如果我使用querydsl进行分组,我不会获得单级条目.反之亦然,在我的解决方案中,我必须执行其他几个步骤.

很高兴知道这是否可以通过使用查询.

Mar*_*ark 2

纯 JPA 和 QueryDsl 仅适用于实体。因此,您可以创建一个数据库视图来聚合您正在查找的数据并将其映射到一个新实体,您可以简单地查询该实体。

另一个解决方案是使用 QueryDsl 的本机 jpa 查询支持。请参阅http://www.querydsl.com/static/querydsl/3.6.1/reference/html/ch02.html下半部分。您将需要最低的段落(查询并投影到 DTO 中)。

归结为:

  • 通过指向数据库(模式)生成 Q 类(我不确定为什么需要它,但它在文档中)
  • 使用 com.mysema.query.jpa.sql.JPASQLQuery 类构造查询
  • 确保在列表方法中列出查询中所有必需的结果字段
  • 创建一个 dto bean 类,您可以将结果投影到其中
  • 将结果投影到 dto 类