1

基準を持つクラスの 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;

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

フィールド someFlag = 0 の MainEntity レコードの secondEntities の数を取得したい

このために、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)));

すべての 2 番目のエンティティの数を取得したい場合、たとえば、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 日間立ち往生して、多分はっきりと考えることができない. 誰かがより多くのコードなどを要求した場合は、このトピックを更新します。すべてのコメントに感謝します。どうもありがとうございました!

4

2 に答える 2

1

サブクエリで正しい軌道に乗っています。JPQL では、「SELECT new MainEntityDto(entity, (select count(secondEntities) from SecondEntity secondEntities where secondEntities.mainEntity = entity and secondEntities.flag=0)) from MainEntity entity」のようになります

基準 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)));

しかし、count で group by を使用する必要があるため、SQL クエリに新しい問題が発生しました。この問題は後で解決され、最終決定を投稿します。この問題を解決するには、複数選択を使用するか、2 番目のクエリを作成しますが、高負荷のアプリケーション アーキテクチャには適していません。また、このクエリの重みが高すぎることが判明したため、再設計される可能性があります

いくつかの重要な情報をUPDします。最初に見つけられなかった理由:

cb.size は int 型を返します -> MainEntityDto では、パラメーター (MainEntity, int) を持つコンストラクターが必要です

cb.count は long 型を返します -> MainEntityDto では、パラメーター (MainEntity、!!LONG!!) を持つコンストラクターが必要です。

これが、最初からこれを作成できなかった理由です。そのクエリはエラーを返しますが、コンストラクターに問題があることを理解していませんでした。

于 2013-11-13T13:38:58.800 に答える