我在使用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天了,也许想不清楚。如果有人要求更多代码等,我会更新这个主题。我非常感谢所有评论,非常感谢你!
答案 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 !!)
这就是为什么我不能在一开始就建立这个。该查询返回错误,但我不明白,构造函数存在问题。