7

次のような3つのテーブルがあります。

A                              AB                        B
-------------                  ------------              ---------------
a1                              a1,b1                    b1

AB は A と B の間の遷移表です。

これにより、私のクラスは、これら2つのクラス内で相互に構成されていません。しかし、JPQLクエリを使用して、ABテーブルのAテーブルの要素にレコードが存在するかどうかを知りたいです。数値またはブール値だけが必要です。

AB は遷移テーブルであるため、モデル オブジェクトはありません。Repository オブジェクトの @Query でこれを実行できるかどうかを知りたいです。

4

3 に答える 3

7

JPQLでクエリを実行するには、ABテーブルをエンティティでモデル化する必要があります。したがって、これを独自のエンティティ クラスとしてモデル化するか、A または B エンティティの関連付けとしてモデル化する必要があります。

于 2013-01-08T08:24:09.890 に答える
5

JPQL の代わりにネイティブ クエリ メソッドを使用することをお勧めします (JPA はネイティブ クエリもサポートしています)。テーブル A が顧客、テーブル B が製品、AB が販売であるとします。これは、顧客が注文した製品のリストを取得するためのクエリです。

entityManager.createNativeQuery("SELECT PRODUCT_ID FROM 
                                     SALE WHERE CUSTOMER_ID = 'C_123'");
于 2013-01-08T08:24:27.793 に答える
3

実際、この状況に対する答えは、あなたが思っているよりも簡単です。適切な仕事に適切なツールを使用するのは簡単なことです。JPA は、複雑な SQL クエリを実装するようには設計されていません。それが SQL の目的です。したがって、JPA を取得して実稼働レベルの SQL クエリにアクセスする方法が必要です。

em.createNativeQuery

したがって、あなたの場合、IDフィールドのみを探してABテーブルにアクセスする必要があります。クエリを取得したら、id フィールドを取得し、id フィールドを使用して Java オブジェクトを検索します。これは真の 2 番目の検索ですが、SQL 標準では些細なことです。

B オブジェクトが参照する回数に基づいて A オブジェクトを探しているとします。B オブジェクトの数に基づいて降順でタイプ A オブジェクトをグループ化する、やや複雑な (しかし典型的な) SQL クエリが必要だとします。これは、プロジェクトの要件に従って実装したい典型的な人気クエリです。

ネイティブ SQL クエリは次のようになります。

select a_id as id from AB group by a_id order by count(*) desc;

ここでやりたいことは、JPA が受け入れることができる形式で id リストが返されることを期待するように JPA に指示することです。追加の JPA エンティティをまとめる必要があります。JPA の通常の方法では決して使用されないもの。しかし、JPA には、照会されたオブジェクトを戻す方法が必要です。この検索クエリのエンティティをそのまままとめます。

@Entity
public class IdSearch {

    @Id
    @Column
    Long id;

    public Long getId() {
            return id;
    }

    public void setId(Long id) {
            this.id = id;
    }
    
}

ここで、2 つのテクノロジを結合するためのコードを少し実装します。

    @SuppressWarnings("unchecked")
    public List<IdSearch> findMostPopularA() {
            return em.createNativeQuery("select a_id as id from AB group by a_id 
            order by count(*) desc", IdSearch.class).getResultList();
    }

以上で、JPA を取得してクエリを正常に完了させるために必要な作業はこれだけです。A オブジェクトを取得するには、従来の JPA アプローチを使用して A リストを相互参照するだけです。

List<IdSearch> list = producer.getMostPopularA();
Iterator<IdSearch> it = list.iterator();
while ( it.hasNext() ) {
    IdSearch a = it.next();
    A object = em.find(A.class,a.getId());
    // your in business!

それでも、上記をもう少し改良することで、実際には SQL 設計構造の多くの機能を考慮して、物事をさらに単純化することができます。少し複雑な SQL クエリは、実際のデータへのさらに直接的な JPA インターフェイスになります。

    @SuppressWarnings("unchecked")
    public List<A> findMostPopularA() {
            return em.createNativeQuery("select * from A, AB 
            where A.id = AB.a_id 
            group by a_id 
            order by count(*) desc", A.class).getResultList();
    }

これにより、interterm IdSearch テーブルが不要になります。

List<A> list = producer.getMostPopularA();
Iterator<A> it = list.iterator();
while ( it.hasNext() ) {
    A a = it.next();
    // your in business!

肉眼ではわかりにくいかもしれませんが、JPA では、JPA インターフェース内で複雑な SQL 構造を利用できるようにする方法が驚くほど単純化されています。次のような SQL を想像してみてください。

SELECT array_agg(players), player_teams
FROM (
  SELECT DISTINCT t1.t1player AS players, t1.player_teams
  FROM (
    SELECT
      p.playerid AS t1id,
      concat(p.playerid,':', p.playername, ' ') AS t1player,
      array_agg(pl.teamid ORDER BY pl.teamid) AS player_teams
    FROM player p
    LEFT JOIN plays pl ON p.playerid = pl.playerid
    GROUP BY p.playerid, p.playername
  ) t1
INNER JOIN (
  SELECT
    p.playerid AS t2id,
    array_agg(pl.teamid ORDER BY pl.teamid) AS player_teams
  FROM player p
  LEFT JOIN plays pl ON p.playerid = pl.playerid
  GROUP BY p.playerid, p.playername
) t2 ON t1.player_teams=t2.player_teams AND t1.t1id <> t2.t2id
) innerQuery
GROUP BY player_teams

要点は、createNativeQuery インターフェイスを使用すると、探しているデータを正確に取得し、Java から簡単にアクセスできるように目的のオブジェクトに直接アクセスできることです。

    @SuppressWarnings("unchecked")
    public List<A> findMostPopularA() {
            return em.createNativeQuery("SELECT array_agg(players), player_teams
            FROM (
                  SELECT DISTINCT t1.t1player AS players, t1.player_teams
                  FROM (
                    SELECT
                      p.playerid AS t1id,
                      concat(p.playerid,':', p.playername, ' ') AS t1player,
                      array_agg(pl.teamid ORDER BY pl.teamid) AS player_teams
                    FROM player p
                    LEFT JOIN plays pl ON p.playerid = pl.playerid
                    GROUP BY p.playerid, p.playername
                  ) t1
                INNER JOIN (
                  SELECT
                    p.playerid AS t2id,
                    array_agg(pl.teamid ORDER BY pl.teamid) AS player_teams
                  FROM player p
                  LEFT JOIN plays pl ON p.playerid = pl.playerid
                  GROUP BY p.playerid, p.playername
                ) t2 ON t1.player_teams=t2.player_teams AND t1.t1id <> t2.t2id
                ) innerQuery
                GROUP BY player_teams
            ", A.class).getResultList();
    }
于 2014-05-23T22:35:25.667 に答える