标准集合 - 字段访问

时间:2013-11-12 19:55:53

标签: java-ee jpa-2.0 eclipselink criteria-api

我在使用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,我可以在我的代码中使用此实体。 但我想得到字段Flag = 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天了,也许想不清楚。如果有人要求更多代码等,我会更新这个主题。我非常感谢所有评论,非常感谢你!

2 个答案:

答案 0 :(得分:1)

您正在使用子查询进入正确的轨道。在JPQL中,它看起来像:  “从MainEntity实体”中选择新的MainEntityDto(实体,(从SecondEntity secondEntities中选择count(secondEntities),其中secondEntities.mainEntity = entity和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));

答案 1 :(得分: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。这个问题将在稍后解决,我将发布最终决定。要解决这个问题,我可以使用多选或进行第二次查询,但它不适合我们的高负载应用程序架构。此外,我们发现此查询的权重太高,可能会重新设计

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

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

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

这就是为什么我不能在一开始就建立这个。该查询返回错误,但我不明白,构造函数存在问题。