JPA GROUP BY实体 – 这可能吗?

是否可以通过引用实体进行分组来选择JPA中的数据?

我的意思是:我有两个实体 – 保险和参考多对一车辆。 保险实体有validTill字段(当然还有车辆字段)。

我想选择车辆,这是最新的保险。 以下查询不起作用:

SELECT DISTINCT v.vehicle, max(v.validTill) as lastValidTill FROM TraInsurance v GROUP BY v.vehicle ORDER BY lastValidTill 

上面的查询失败并显示错误:

 ERROR: column "travehicle1_.id_brand" must appear in the GROUP BY clause or be used in an aggregate function 

这是因为JPA将引用车辆的所有字段添加到查询而不是GROUP BY。 这是我做错了吗? 或者也许只是不可能这样做?

编辑:

TraInsurance实体

 @Entity @Table(name = "TRA_INSURANCES", schema="public") @SequenceGenerator(name = "TRA_INSURANCES_SEQ", sequenceName = "TRA_INSURANCES_SEQ", allocationSize = 1) public class TraInsurance implements EntityInt, Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "id", nullable = false) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TRA_INSURANCES_SEQ") private Long id; @NotNull @ManyToOne @JoinColumn(nullable = false, name = "id_vehicle") private TraVehicle vehicle; @NotNull @Column(name = "valid_from", nullable = false) private Date validFrom; @Column(name = "valid_till", nullable = false) private Date validTill; @NotNull @ManyToOne @JoinColumn(nullable = false, name = "id_company") private Company company; @Column(name = "policy_no", nullable = true, length = 50) private String policyNumber; @Column(name = "rate", nullable = true, precision = 12, scale = 2) private BigDecimal rate; @Column(name = "discount_percent", nullable = true) private Float discountPercent; @Column(nullable = true) private String description; public TraInsurance() {} public Long getId() { return id; } public void setId(Long id) { this.id = id; } public TraVehicle getVehicle() { return vehicle; } public void setVehicle(TraVehicle vehicle) { this.vehicle = vehicle; } public Date getValidFrom() { return validFrom; } public void setValidFrom(Date validFrom) { this.validFrom = validFrom; } public Date getValidTill() { return validTill; } public void setValidTill(Date validTill) { this.validTill = validTill; } public Company getCompany() { return company; } public void setCompany(Company company) { this.company = company; } public String getPolicyNumber() { return policyNumber; } public void setPolicyNumber(String policyNumber) { this.policyNumber = policyNumber; } public BigDecimal getRate() { return rate; } public void setRate(BigDecimal rate) { this.rate = rate; } public Float getDiscountPercent() { return discountPercent; } public void setDiscountPercent(Float discountPercent) { this.discountPercent = discountPercent; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((validFrom == null) ? 0 : validFrom.hashCode()); result = prime * result + ((vehicle == null) ? 0 : vehicle.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof TraInsurance)) return false; TraInsurance other = (TraInsurance) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (validFrom == null) { if (other.validFrom != null) return false; } else if (!validFrom.equals(other.validFrom)) return false; if (vehicle == null) { if (other.vehicle != null) return false; } else if (!vehicle.equals(other.vehicle)) return false; return true; } } 

请在此用例中明确使用JOIN

 SELECT ve, MAX(v.validTill) FROM TraInsurance v JOIN v.vehicle ve GROUP BY ve ORDER BY MAX(v.validTill) 

显然JPA规范允许,但至少Hibernate的实现不支持它(参见HHH-2436和HHH-1615 )。

如果在GROUP BY中传递一个实体,Hibernate会自动将其id添加到底层数据库的转换后的SQL中。 此外,GROUP BY中的值必须存在于SELECT子句中。 因此,您可以选择其ID,而不是选择整个对象,然后从这些ID中 ,您可以再次检索该对象。

  SELECT DISTINCT v.vehicle.id, max(v.validTill) FROM TraInsurance v GROUP BY v.vehicle.id ORDER BY max(v.validTill) 

如果需要时间并且需要DB命中从其ID中检索Vehicle对象,则可以在SELECT中选择所有Vehicle的属性并将它们放入GROUP BY中。 然后,您可以从这些属性构造Vehicle对象,而无需访问DB。