我发现了一个奇怪的行为,我想知道我是否滥用了 JPA 或者它是否是 Spring 回归。
这是我的实体:
@Entity
public class Brand {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
@EqualsAndHashCode.Include
@Schema(description = "Brand's id", example = "1")
private Long id;
// ...
}
@Entity
public class Product {
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "product_brands", joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "brands_id"))
private List<Brand> brands;
// ...
}
我有这个要求:
@Query("select new com.mypackage.Statistic(br, count(p)) " +
"from Lot l join l.products p join p.brands br " +
"group by br " +
"order by count(p) desc")
List<Statistic<Brand>> groupByProductBrand();
这在 Spring Boot 2.5.4 中工作正常,然后我更新到版本 3.1.6,现在出现此错误:
ERROR: column "b1_1.id" must appear in the GROUP BY clause or be used in an aggregate function<EOL>
执行的请求是:
select b1_1.id, ..., count(p1_0.products_id)
from lot l1_0
join (lot_products p1_0 join product p1_1 on p1_1.id=p1_0.products_id) on l1_0.id=p1_0.lot_id
join (product_brands b1_0 join brand b1_1 on b1_1.id=b1_0.brands_id) on p1_1.id=b1_0.product_id
group by b1_0.brands_id
order by count(p1_0.products_id) desc offset;
经过一些测试,在 select 和 group by 子句中给出所有列名后,看起来 select 中的 br.id 是从 Brands 表(b1_1)中获取的,而 group by 中的 br.id 是从关联表中获取的( b1_0)。值显然是相同的,但在这个用例中,sql 查询失败。
我猜您必须在
group by
子句中使用单值路径表达式(或标识变量),可以使用 IN
关键字获得。
尝试以下两个查询(不确定哪一个在语法上是正确的,尽管我相信它应该是第一个或两个):
"select new com.mypackage.Statistic(br, count(p)) " +
"from Lot l join l.products p, IN(p.brands) br " +
"group by br " +
"order by count(p) desc"
或
"select new com.mypackage.Statistic(br.brand, count(p)) " +
"from Lot l join l.products p, IN(p.brands) br " +
"group by br.brand " +
"order by count(p) desc"