1. 概要

この短いチュートリアルでは、JPAクエリで複数の異なるエンティティを返す方法を説明します。

まず、いくつかの異なるエンティティを含む簡単なコード例を作成します。 次に、複数の異なるエンティティを返すJPAクエリを作成する方法について説明します。 最後に、HibernateのJPA実装での実用的な例を示します。

2. 構成例

1つのクエリで複数のエンティティを返す方法を説明する前に、作業する例を作成しましょう。

ユーザーが特定のテレビチャンネルの定期購入を購入できるアプリを作成します。 チャネルサブスクリプション、およびユーザーの3つのテーブルで構成されています。

まず、Channelエンティティを見てみましょう。

@Entity
public class Channel {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String code;

    private Long subscriptionId;

   // getters, setters, etc.
}

これは、対応する列にマップされる3つのフィールドで構成されます。 最初で最も重要なものはid、であり、これは主キーでもあります。 code フィールドに、Channelのコードを保存します。

最後になりましたが、subsetId列もあります。 これは、チャネルとそれが属するサブスクリプションの間の関係を作成するために使用されます。 1つのチャネルが異なるサブスクリプションに属することができます。

それでは、Subscriptionエンティティを見てみましょう。

@Entity
public class Subscription {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String code;

   // getters, setters, etc.
}

最初のものよりもさらに簡単です。 これは、主キーである id フィールドと、サブスクリプションのcodeフィールドで構成されます。

Userエンティティも見てみましょう。

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String email;

    private Long subscriptionId;

    // getters, setters, etc.
}

主キーのidフィールドに加えて、emailフィールドとsubscriptionIdフィールドで構成されています。 後者は、ユーザーとユーザーが選択したサブスクリプションの間に関係を作成するために使用されます。

3. クエリで複数のエンティティを返す

3.1. クエリの作成

複数の異なるエンティティを返すクエリを作成するには、2つのことを行う必要があります。

まず、SQLクエリのSELECT部分に返すエンティティをコンマで区切って一覧表示する必要があります。

次に、主キーと対応する外部キーを使用して、それらを相互に接続する必要があります。

私たちの例を見てみましょう。 指定された電子メールでユーザーが購入したサブスクリプションに割り当てられたすべてのチャネルをフェッチするとします。JPAクエリは次のようになります。

SELECT c, s, u
  FROM Channel c, Subscription s, User u
  WHERE c.subscriptionId = s.id AND s.id = u.subscriptionId AND u.email=:email

3.2. 結果の抽出

複数の異なるエンティティを選択するJPAクエリは、それらをObjectsの配列で返します。 指摘する価値があるのは、配列がエンティティの順序を維持していることです。 返されたオブジェクトを特定のエンティティクラスに手動でキャストする必要があるため、これは重要な情報です。

それが実際に動いているのを見てみましょう。 クエリを作成して結果をフェッチする専用のリポジトリクラスを作成しました。

public class ReportRepository {
    private final EntityManagerFactory emf;

    public ReportRepository() {
        // create an instance of entity manager factory
    }

    public List<Object[]> find(String email) {
        EntityManager entityManager = emf.createEntityManager();
        Query query = entityManager
          .createQuery("SELECT c, s, u FROM  Channel c, Subscription s, User u" 
          + " WHERE c.subscriptionId = s.id AND s.id = u.subscriptionId AND u.email=:email");
        query.setParameter("email", eamil);

        return query.getResultList();
    }
}

前のセクションの正確なクエリを使用しています。 次に、結果を絞り込むために電子メールパラメータを設定します。 最後に、結果リストを取得します。

フェッチされたリストから個々のエンティティを抽出する方法を見てみましょう。

List<Object[]> reportDetails = reportRepository.find("[email protected]");

for (Object[] reportDetail : reportDetails) {
    Channel channel = (Channel) reportDetail[0];
    Subscription subscription = (Subscription) reportDetail[1];
    User user = (User) reportDetail[2];
    
    // do something with entities
}

フェッチされたリストを繰り返し処理し、指定されたオブジェクト配列からエンティティを抽出します。 JPAクエリとそのSELECTセクションのエンティティの順序を考慮して、最初の要素として Channel エンティティを取得し、2番目の要素としてSubscriptionエンティティを取得します。 、および配列の最後の要素としてのUserエンティティ。

4. 結論

この記事では、JPAクエリで複数のエンティティを返す方法について説明しました。 まず、この記事の後半で取り組んだ例を作成しました。 次に、JPAクエリを記述して複数の異なるエンティティを返す方法を説明しました。 最後に、結果リストからそれらを抽出する方法を示しました。

いつものように、記事の完全なソースコードは、GitHubから入手できます。