【问题标题】:JPA criteria query countJPA 条件查询计数
【发布时间】:2018-01-29 12:34:03
【问题描述】:

我在使用 CriteriaBuilder 计算实体时遇到问题。首先,我有两个实体 - 类别和项目。类别是对象的树,可以有一个父级、许多子类别和项目。 这是我在 mysql 中的实际数据:

Category 0
  Category 0 0
    10 items
  Category 0 1
    10 items
  Category 0 2
    10 items
  Category 0 3
    10 items
Category 1
  Category 1 0
    10 items
  Category 1 1
    10 items
  Category 1 2
    10 items
  Category 1 3
    10 items

类别实体:

@ManyToOne
private Category category;

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Category> subcategories = new ArrayList<>();

@OneToMany(cascade = CascadeType.ALL)
private List<ItemForSale> items = new ArrayList<>();

public List<Category> getAllCategories() {
    List<Category> categories = new ArrayList<>();
    categories.add(this);
    getSubcategories().forEach((c) -> {
        categories.addAll(c.getAllCategories());
    });
    return categories;
}

我的计数查询应该根据条件计数项目

public int getItemsForSaleCount(Category category) {
    CriteriaBuilder cm = em.getCriteriaBuilder();
    CriteriaQuery<Long> cq = cm.createQuery(Long.class);
    Root<ItemForSale> root = cq.from(ItemForSale.class);
    cq.select(cm.count(cq.from(ItemForSale.class)));
    List<Category> categories = category.getAllCategories();
    if(categories.size() > 1) {
        List<Predicate> predicates = new ArrayList<>();
        categories.forEach((c) -> {
            predicates.add(cm.equal(root.get("category"), c));
        });
        cq.where(cm.or(predicates.toArray(new Predicate[predicates.size()])));
    } else {
        cq.where(cm.equal(root.get("category"), category));
    }
    Query query = em.createQuery(cq);
    return Math.toIntExact((Long) query.getSingleResult());
}

基本上发生的情况是,当我请求类别 0 时,例如查询结果应该是 40,但是 40 * 80 = 3200(正确结果 * 项目总数),当我请求子类别时,结果是 10 * 80 = 800

编辑: 我解决了,当我用 root 替换 cq.from(ItemForSale.class)) 时它正在工作,有人可以解释一下区别吗?

【问题讨论】:

    标签: jpa count persistence criteria builder


    【解决方案1】:

    好吧,AbstractQuery.fromJavadoc 回答了你的问题:

    创建并添加与给定实体对应的查询根,与任何现有根形成笛卡尔积

    由于您调用了两次from,并将where 子句定义为仅涉及其中一个根,因此查询返回来自“过滤”根的 40 行与来自“未过滤”的 80 个结果交叉连接根。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-22
      • 2011-10-13
      相关资源
      最近更新 更多