0

メインクエリとサブクエリで WHERE ステートメントを明確に定義しました。サブクエリを省略した場合、これは JPA ログに出力されます。ただし、サブクエリを追加すると、同じwhere句は適用されません。WHERE 句 (選択 σ) を省略した JPA Criteria クエリについてはどうですか?

    // 1) MainQuery
    // Create the FROM
    Root<PubThread> rootPubThread = cq.from(PubThread.class);
    // Create the JOIN fro the first select: join-chaining. You only need the return for ordering. e.g. cq.orderBy(cb.asc(categoryJoin.get(Pub_.title)));
    Join<Pub, PubCategory> categoryJoin = rootPubThread.join(PubThread_.pups).join(Pub_.pubCategory);
    // Create the WHERE
    cq.where(criteriaBuilder.not(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId)));
    // Create the SELECT, at last
    cq.select(rootPubThread).distinct(true);

    // 2) Subquery
    Subquery<PubThread> subquery = cq.subquery(PubThread.class); 
    Root<PubThread> rootPubThreadSub = subquery.from(PubThread.class); 
    subquery.where(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId));
    Join<Pub, PubCategory> categoryJoinSub = rootPubThreadSub.join(PubThread_.pups).join(Pub_.pubCategory);
    subquery.select(rootPubThreadSub);

    Predicate correlatePredicate = criteriaBuilder.equal(rootPubThreadSub.get(PubThread_.id), rootPubThread);
    subquery.where(correlatePredicate);
    cq.where(criteriaBuilder.exists(subquery));

このクエリの出力は次のとおりです。

select distinct
    pubthread0_.id as id3_,
    pubthread0_.dateCreated as dateCrea2_3_,
    pubthread0_.dateModified as dateModi3_3_,
    pubthread0_.name as name3_
from
    pubthread pubthread0_
        inner join
    pub_pubthread pups1_ ON pubthread0_.id = pups1_.pubThreads_id
        inner join
    pub pub2_ ON pups1_.pups_id = pub2_.id
        inner join
    PubCategory pubcategor3_ ON pub2_.pubCategoryId = pubcategor3_.id
where 
    exists( select 
            pubthread4_.id
        from
            pubthread pubthread4_
                inner join
            pub_pubthread pups5_ ON pubthread4_.id = pups5_.pubThreads_id
                inner join
            pub pub6_ ON pups5_.pups_id = pub6_.id
                inner join
            PubCategory pubcategor7_ ON pub6_.pubCategoryId = pubcategor7_.id
        where
             pubthread4_.id=pubthread0_.id)
4

1 に答える 1

0

とった。述語を定義するとすぐに、where 句は拒否されます。それは確かです。where 句をインスタンス内の接続詞と組み合わせて、where 句にPredicate追加します。を使用しcriteriaBuilder.and(..., ...)ます。意味的に同じことをする。

したがって、2 つの接続述語があります。1 つはサブクエリ用で、もう 1 つはメイン クエリ用です。select(...)私がコードから除外した廃止されたシングルに注意してください(コメントされています)。

    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
    CriteriaQuery<PubThread> mainQuery = criteriaBuilder
            .createQuery(PubThread.class);

    // 1) MainQuery
    // Create the FROM
    Root<PubThread> rootPubThread = mainQuery.from(PubThread.class);
    // Create the JOIN from the first select: join-chaining. You only need the return for ordering. e.g. cq.orderBy(cb.asc(categoryJoin.get(Pub_.title)));
    Join<Pub, PubCategory> categoryJoin = rootPubThread.join(PubThread_.pups).join(Pub_.pubCategory);
    // Create the WHERE
    mainQuery.where(criteriaBuilder.not(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId)));
    // Create the SELECT, at last
    mainQuery.select(rootPubThread).distinct(true);

    // 2) Subquery
    Subquery<PubThread> subquery = mainQuery.subquery(PubThread.class); 
    Root<PubThread> rootPubThreadSub = subquery.from(PubThread.class); 
    //subquery.where(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId));
    Join<Pub, PubCategory> categoryJoinSub = rootPubThreadSub.join(PubThread_.pups).join(Pub_.pubCategory);
    subquery.select(rootPubThreadSub);

    //Predicate correlatePredicate = criteriaBuilder.equal(rootPubThreadSub.get(PubThread_.id), rootPubThread);
    Predicate correlatePredicate = criteriaBuilder.and(
            criteriaBuilder.equal(rootPubThreadSub.get(PubThread_.id), rootPubThread),
            criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId)
            );
    subquery.where(correlatePredicate);     

    //Predicate correlatePredicate = criteriaBuilder.equal(rootPubThreadSub.get(PubThread_.id), rootPubThread);
    Predicate mainPredicate = criteriaBuilder.and(
            criteriaBuilder.not(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId)),
            criteriaBuilder.exists(subquery)
            );
    //cq.where(criteriaBuilder.exists(subquery));
    mainQuery.where(mainPredicate);


    TypedQuery<PubThread> typedQuery = em.createQuery(mainQuery);
    List<PubThread> otherPubThreads = typedQuery.getResultList();

    return otherPubThreads;

結果はこのようなものです

    where
    pubthread4_.id=pubthread0_.id 
    and pubthread0_.id=1
于 2013-09-06T09:50:28.803 に答える