java - 在 JPA 中以多对多关系编写计数聚合函数会引发 Hibernate 错误

标签 java jpa spring-data-jpa

我有两个实体(订单和产品),它们通过链接表相互具有多对多关系。我需要退回所有订单中产品数量> 2的订单。我的型号如下

@Data
@Entity
@Table(name = "orders")
@JsonInclude(NON_NULL)
public class Order implements Serializable {

   public static final int PRECISION = 2;

   @Id
  @GeneratedValue(strategy = IDENTITY)
  @JsonIgnore
  private String orderId;

  @ManyToMany(fetch = EAGER, cascade = ALL)
  @JoinTable(
        name = "order_product",
        joinColumns = @JoinColumn(name = "order_id", updatable = false, nullable = false),
        inverseJoinColumns = @JoinColumn(name = "product_id", updatable = false, nullable = false)
)
  @JsonBackReference
  private List<Product> products = new ArrayList<>();

. . . . Getters and Setters

}

产品

@Data
@Entity
@Table(name = "products")
public class Product implements Serializable {

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @JsonIgnore
    private String productId;

    @JoinTable(name = "order_product", 
        joinColumns = {@JoinColumn(name = "product_id")},
        inverseJoinColumns = {@JoinColumn(name = "order_id")})
    @ManyToMany(fetch = FetchType.EAGER, cascade= CascadeType.ALL)
    @JsonBackReference
    private List<Order> orders;

    . . . Getters and setters . . .

}

我想获取所有订单及其产品,其中产品中的订单数大于 2。

我尝试了同一查询的多种变体。 (查看评论的)

@Repository
public interface OrderRepository extends JpaRepository<Order, Serializable> {

  //@Query("SELECT o from Order o INNER JOIN o.products GROUP BY o.orderId HAVING count(o.products) > 2")
  //@Query("select o from Orders o join o.products p GROUP BY o.orderId HAVING COUNT(p) > 2")
  @Query("SELECT o from Order o join o.products p having count(p) > 2")
  List<Order> findOrderWithMultipleProducts();
}

如果我对域的建模不正确,请告诉我。

我遇到的错误之一是

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: having near line 1, column 70 [SELECT o from com.jpa.orders.domain.Order o join o.products p having count(p) > 2]
    at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:91) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:288) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:187) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:76) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:150) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:302) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:240) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1894) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:291) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    ... 62 common frames omitted

最佳答案

你想要这样的东西:

@Query("SELECT o FROM Order o WHERE size(o.products) > 2")

关于获取订单旁边的产品,我通常使用@NamedEntityGraph。在您的情况下,将类似的内容放在您的 Order 实体之上:

@NamedEntityGraph(name = "OrderWithProducts",
    attributeNodes = {
            @NamedAttributeNode(value="products")
    }
)

然后将其添加到您的存储库方法中:

@EntityGraph(value = "OrderWithProducts" , type=EntityGraphType.FETCH)

这将连接实体并使用一个查询获取您的数据。当然,您总是希望查看 SQL Hibernate 为您生成的内容并根据您的需求进行优化。

关于java - 在 JPA 中以多对多关系编写计数聚合函数会引发 Hibernate 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50547550/

相关文章:

java - 相当于使用变元而不是构造函数的 NEW 运算符

spring-boot - Multi-Tenancy : Managing multiple datasources with Spring Data JPA

java - 如何读取文件内容,写入输出流以及重新读取并存储在java内存中的字符串变量中

java - 从异步任务类获取值到另一个类

java - 使用 bouncycaSTLe 进行椭圆曲线加点

java - Spring 数据 JPA : find nested object

java - Spring Boot JPA 查询使用 isempty 和 isnull 关键字

使用 google-rfc-2445 库的 java.text.parse 异常

java - System.getproperty ("spring.profiles.active") 在 JPA 实体监听器中始终为 Null

java - JPA 配置 boolean 字段以保留为整数