【问题标题】:How to group or sum up data within @ElementCollection by JPQL?如何通过 JPQL 对 @ElementCollection 中的数据进行分组或汇总?
【发布时间】:2025-12-02 07:50:01
【问题描述】:

我有一个类包含从交易到交易金额的多对多关系

Class Deal{
.....

private String name;

private String department;

private DealType type;

@AttributeOverrides({
    @AttributeOverride(name="value.in.available", column=@Column(name="in_avl")),
    @AttributeOverride(name="value.in.unavailable", column=@Column(name="in_unv")),
    @AttributeOverride(name="value.out.available", column=@Column(name="out_avl")),
    @AttributeOverride(name="value.out.unavailable", column=@Column(name="out_unv"))
})
@ElementCollection(fetch = FetchType.EAGER)
private Map<Transaction, AmountBucket> transactionAmounts= new TreeMap<Coffer, AmountBucket>();
}

那么 Entity AmountBucket 是这样的:

Class AmountBucket{
    private Amount in;
    private Amount out;
}

Class Amount{
    private BigDecimal available;
    private BigDecimal unavaiable;
}

但出于@ElementCollection 的目的,树层次结构使用@AttributeOverride 存储在单个表中。

这里的目标是总结transactionAmounts,而不考虑DealType。如果它没有选择可爱的@ElementCollection 功能,那么我们可以在 JPQL 中进行内部连接,然后进行分组,但是当我尝试使用 ElementCollection 结构按 JPQL 对内容进行分组时,就会出现问题:

Failed to execute query 
"SELECT NEW DEAL(d.name, d.department, SUM(d.transactionAmounts)) FROM 
Deal AS d GROUP BY d.name, d.department". 
Check the query syntax for correctness. See nested exception for details.; nested 
exception is <openjpa-2.2.0-r422266:1244990 nonfatal user error>    org.apache.openjpa.persistence.ArgumentException: Failed to execute query ......

可能是d.transactionAmounts 无法总结,因为它是@CollectionElement?我有一个为此 JPQL 查询服务的构造函数:

public Deal(String name, String department, Map<Transaction, AmountBucket> transactionAmounts) {
    this.name= name;
    this.department= department;
    this.transactionAmounts= transactionAmounts;
    this.type = DealType.SUM;
}

我真的没有在 JPQL 中看到任何语法问题,也没有看到任何关于如何对 @ElementCollection 中的值进行分组和汇总的文档。请帮忙谢谢。

【问题讨论】:

  • 你能发布更多的堆栈跟踪吗?
  • @Andrei I 堆栈跟踪确实没有说明太多,只是说 JPQL 有语法错误。我敢打赌应该还有其他东西,但 OpenJPA 不会输出到日志中。

标签: java spring jakarta-ee jpa ejb


【解决方案1】:

问题似乎出在构造函数中:它没有正确的签名。它应该有以下一个:

public Deal(String name, String department, long transactionAmount);//you might try also with int instead of long

因为SUM(d.transactionAmounts) 返回一个数字,而不是您在构造函数中的MAP

【讨论】:

  • 谢谢。但我认为transactionAmount 的类型为Map&lt;Transaction, AmountBucket&gt; 而不是Long。我正在考虑使用SELECT NEW DEAL(d.name, d.department, SUM(d.value.in.available), SUM(d.value.in.unavailable),SUM(d.value.out.available),SUM(d.value.out.unavailable)),但仍然无法正常工作。因为我认为 JPQL 无法将 value 识别为 transactionAmount 字段。真拉我的头发找到一种总结地图值的方法。
  • 您没有理解 JPQL 中的SUM() 表达式返回一个由 long 或 int 表示的 数字。它不能是 MAP。如果您想要具有 4 个 long 的构造函数,它应该可以工作,但它绝对不是 MAP。
  • 你是对的。那么如何在 JPQL 中检索地图的键或值,然后我可以使用正确的 select SUM() 查询构造新实体?谢谢。
  • 我在这里看到了您的后续问题:*.com/questions/20229155/… 如果得到解决,请将其标记为已解决。