1

我在使用 Criteria 的班级中访问 Collection-field 时遇到问题。

我有 2 个实体:首先,映射到其他实体

@Table(name = "MAIN_ENTITY")
public class MainEntity {

    @Id
    @Column(name = ID_MAIN, nullable = false, precision = 38, scale = 0)
    private BigDecimal id;

    @OneToMany(mappedBy = "mappedField")
    private Set<SecondEntity> secondEntities = new HashSet<>(0); 

    ...................
}

第二,加载到第一个实体。

@Table(name = "SECOND_ENTITY")
public class SecondEntity {

    @Id
    @Column(name = ID_SECOND, nullable = false, precision = 38, scale = 0)
    private BigDecimal id;

    @Column(name = SOME_FLAG, nullable = false, precision = 38, scale = 0)
    private BigDecimal someFlag;

    @ManyToOne
    @JoinColumn(name = MAIN_ENTITY_FK, nullable = false)
    private MainEntity mainEntity;

    ...................
}

我想获取 MainEntity 记录中的 secondEntities 计数,其中字段 someFlag = 0

为此,我有扩展 MainEntity 并具有字段计数的类

public class MainEntityDto extends MainEntity {
    private MainEntity entity;
    private Integer count;
    ...................
}

然后我正在尝试构建查询,我写了这个:

Path secondEntitiesPath = root.<Set>get("secondEntities");
cq.select(cb.construct(MainEntityDto.class, root, cb.size(secondEntitiesPath)));

如果我想计算所有第二个实体的数量,这很好用,例如,如果我有 100 个实体,我将得到 count = 100,我可以稍后在我的代码中使用这个实体。但我想获得字段标志 = 0 的实体计数。我试图写类似的东西

cq.select(cb.construct(MainEntityDto.class, root, 
    cb.size(secondEntitiesPath))).where(cb.equal(
    secondEntitiesPath.<BigDecimal>get("Flag"), BigDecimal.ZERO)

但这只是创建了另一个连接,对计数没有影响,它仍然返回 100。我只是无法在我的查询中访问 Set 的元素。我以一百种不同的方式尝试它,但我总是有类似的东西

SELECT COUNT(t.id)
FROM SECOND_ENTITY se
WHERE (se.MAIN_ENTITY_FK = mainEntity.ID)

在它之后,我有另一个加入,有条件,我写的。

对不起,伙计们,如果它看起来像一团糟,你什么都不懂。我被困了3天,可能无法清楚地思考。如果有人要求更多代码等,我将更新此主题。我将非常感谢所有评论,非常感谢!

4

2 回答 2

1

您在子查询的正确轨道上。在 JPQL 中,它看起来像:“从 MainEntity 实体中选择新 MainEntityDto(entity, (select count(secondEntities) from SecondEntity secondEntities where secondEntities.mainEntity = entity and secondEntities.flag=0))”

使用标准 API 看起来像:

Subquery sq = cb.subquery(SecondEntity.class);
Root<SecondEntity> second= sq.from(SecondEntity.class);
sq.select(cb.count(second));
sq.where(cb.and(cb.equal(second.get("mainEntity"), root), cb.equal(second.get("flag"), 0));

cq.select(cb.construct(CodeSubjectDto.class, root, sq));
于 2013-11-13T14:00:42.480 回答
0

我有一些建议,现在计算一些条件条件查询应该是这样的

final Join<MainEntity, SecondEntity> secondEntityJoin =
    root.join(secondEntities, JoinType.LEFT);
secondEntityJoin.on(cb.equal(secondEntityJoin.<BigDecimal>get("someFlag"), BigDecimal.ZERO))); 
cq.select(cb.construct(CodeSubjectDto.class, root, cb.count(secondEntityJoin)));

但是现在SQL查询出现了新问题,因为我必须使用group by with count。这个问题将在稍后解决,我将发布最终决定。为了解决这个问题,我可以使用多选,或者进行第二次查询,但这不适合我们的高负载应用程序架构。我们也发现这个查询的权重太高,可能会重新设计

UPD一些重要信息,为什么我一开始没有找到它:

cb.size 返回类型 int -> 在 MainEntityDto 我必须有带参数的构造函数(MainEntity,int)

cb.count 返回类型 long -> 在 MainEntityDto 我必须有带参数的构造函数(MainEntity,!!LONG!!)

这就是为什么我一开始就无法构建它的原因。该查询返回错误,但我不明白,构造函数有问题。

于 2013-11-13T13:38:58.800 回答