【问题标题】:Criteria collection-field access标准集合字段访问
【发布时间】:2013-11-25 03:52:33
【问题描述】:

我在使用 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天,可能无法清楚地思考。如果有人要求更多代码等,我会更新这个主题。我将非常感谢所有 cmets,非常感谢!

【问题讨论】:

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


    【解决方案1】:

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

    使用标准 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));
    

    【讨论】:

      【解决方案2】:

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

      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 类型 -> 在 MainEntityDto 中我必须有带参数的构造函数(MainEntity, int)

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

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

      【讨论】:

        猜你喜欢
        • 2016-09-21
        • 1970-01-01
        • 2020-03-28
        • 2021-06-13
        • 1970-01-01
        • 1970-01-01
        • 2011-11-12
        • 2015-06-06
        • 1970-01-01
        相关资源
        最近更新 更多