REST風サービスをJavaEEで構築する方法12(DAO層編3)

前回SQLを使用して、1つテーブルに対して検索する方法を紹介した。
今回はSQLを使用して、複数テーブルを結合した検索の方法を紹介する。

<前提条件>
下記の記事を読了していること。
REST風サービスをJavaEEで構築する方法01(導入編)
REST風サービスをJavaEEで構築する方法02(雛形プロジェクト編)
REST風サービスをJavaEEで構築する方法03(RESTクライアント編)
REST風サービスをJavaEEで構築する方法04(各メソッド編)
REST風サービスをJavaEEで構築する方法05(パラメータの受け取り編)
REST風サービスをJavaEEで構築する方法06(JSON返却編1)
REST風サービスをJavaEEで構築する方法07(JSON返却編2)
REST風サービスをJavaEEで構築する方法08(Logic層編)
REST風サービスをJavaEEで構築する方法09(DB接続設定編)
REST風サービスをJavaEEで構築する方法10(DAO層編1)
REST風サービスをJavaEEで構築する方法11(DAO層編2)

接続するDB(MySQL)に下記のテーブルが作成されていること。
(前回まで使用してきた「SAMPLE_TBL」と結合するテーブルとして追加する)


テーブル名:SAMPLE_DETAIL_TBL

No. カラム名 主キー 制約
1 ID CHAR 4 NOT NULL
2 DETAIL_ID CHAR 2 NOT NULL
3 REMARKS VARCHAR 256   -

<全体像から見た位置づけ>
CompositeKeyクラスを作成する。EntityクラスとDao層クラスを追加作成する。

<手順概要>
1.CompositeKeyクラスを作成する
2.Entityクラスを作成する
3.Dao層クラスを作成する
4.Logic層・Api層・index.htmlを編集する

<手順詳細>
1.CompositeKeyクラスを作成する
Entityクラスでは主キーを表す「@Id」を付与できるプロパティは基本的に1つだけである。
複数の列の組み合わせをキーとする場合は、キーの要素となるプロパティを持つ、CompositeKeyクラスを作成し、Entityクラスの@IdClassアノテーションで指定する必要がある。

プロジェクトツリー上で右クリックし、[新規]>[Javaクラス]を選択する。
表示されたダイアログのクラス名に「SampleJoinKey」(※)、パッケージに「lab.moonmt.SampleRest.entity.key」(※)と設定し、【終了(F)】ボタンを押下する。
(※)任意の名前をつけることができる。

作成されたクラスを下記の様に編集する。

package lab.moonmt.SampleRest.entity.key;

import java.io.Serializable;

public class SampleJoinKey implements Serializable {
    
    public String id;           //...(1)			
    public String detail_id;	//...(1)
	
	//...(※※)
}


ソースコード解説

番号 説明
(1) 複合キーを構成する列名をプロパティとして定義する。

ここまで記述して、(※※)付近で右クリックし「コードの挿入...」を選択する。

表示されたメニューで「equals()およびhashCode()...」を押下する。

それぞれのメソッドに含めるフィールドを聞かれるので、すべてにチェックをいれて、【生成】ボタンを押下する。

メソッドが自動生成されて、下記の様な状態になったことを確認する。

package lab.moonmt.SampleRest.entity.key;

import java.io.Serializable;
import java.util.Objects;

public class SampleJoinKey implements Serializable {
    
    public String id;
    public String detail_id;

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 97 * hash + Objects.hashCode(this.id);
        hash = 97 * hash + Objects.hashCode(this.detail_id);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final SampleJoinKey other = (SampleJoinKey) obj;
        if (!Objects.equals(this.id, other.id)) {
            return false;
        }
        if (!Objects.equals(this.detail_id, other.detail_id)) {
            return false;
        }
        return true;
    }
}

2.Entityクラスを作成する
プロジェクトツリー上で右クリックし、[新規]>[Javaクラス]を選択する。
表示されたダイアログのクラス名に「SampleJoinEntity」(※)、パッケージに「lab.moonmt.SampleRest.entity」(※)と設定し、【終了(F)】ボタンを押下する。
(※)任意の名前をつけることができる。

作成されたクラスを下記の様に編集する。

package lab.moonmt.SampleRest.entity;

import lab.moonmt.SampleRest.entity.key.SampleJoinKey;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;

@Entity
@IdClass(value=SampleJoinKey.class)			//...(1)
@NamedNativeQueries({					//...(2)
@NamedNativeQuery(					//...(3)
        name="joinSql",
        query="select s.ID, d.DETAIL_ID, s.NAME, d.REMARKS " +
              "from SAMPLE_TBL s, SAMPLE_DETAIL_TBL d " +
              "where s.ID = d.ID " +
              "order by s.ID, d.DETAIL_ID;",
        resultClass=SampleJoinEntity.class),
@NamedNativeQuery(					//...(4)
        name="joinSql2",
        query="select s.ID, d.DETAIL_ID, s.NAME, d.REMARKS " +
              "from SAMPLE_TBL s, SAMPLE_DETAIL_TBL d " +
              "where s.ID = d.ID " +
              "and   d.REMARKS = ?remarks " +
              "and   d.DETAIL_ID = ?dId " +
              "order by s.ID, d.DETAIL_ID;",
        resultClass=SampleJoinEntity.class)
})
public class SampleJoinEntity implements Serializable {
    
    @Id
    private String id;					//...(5)
    
    @Id
    private String detail_id;				//...(5)

    private String name;
    
    private String remarks;

    public String getId() {
        return id;
    }

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

    public String getDetail_id() {
        return detail_id;
    }

    public void setDetail_id(String detail_id) {
        this.detail_id = detail_id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getRemarks() {
        return remarks;
    }

    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }
}


ソースコード解説

番号 説明
(1) @IdClassアノテーションを使用して、手順1で作成したCompositeKeyクラスを指定している。
(2) NamedNativeQueriesアノテーションを使用して、複数のSQLを記述することを宣言している。
(3) @NamedNativeQueryアノテーションを使用して、1つ目のSQLを記述している。(記述しているSQLは2つのテーブルを結合している)
(4) @NamedNativeQueryアノテーションを使用して、2つ目のSQLを記述している。(記述しているSQLは2つのテーブルを結合している)
(5) (1)でCompositeKeyクラスを@IdClassで指定しているので、複数のプロパティに@Idをつけても警告が発生しない。

3.Dao層クラスを作成する
プロジェクトツリー上で右クリックし、[新規]>[Javaクラス]を選択する。
表示されたダイアログのクラス名に「SampleJoinDao」(※)、パッケージに「lab.moonmt.SampleRest.dao」(※)と設定し、【終了(F)】ボタンを押下する。
(※)任意の名前をつけることができる。

作成されたクラスを下記の様に編集する。

package lab.moonmt.SampleRest.dao;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import lab.moonmt.SampleRest.entity.SampleJoinEntity;

@Stateless
public class SampleJoinDao {
    
    @PersistenceContext
    private EntityManager em;
    
    public List<SampleJoinEntity> getJoinInfo(){
        
        Query query = em.createNamedQuery("joinSql");   //...(1)
        
        return query.getResultList();                   //...(3)
    }
    
    public List<SampleJoinEntity> getJoinInfo2(String dId, String remarks){
        
        Query query = em.createNamedQuery("joinSql2");   //...(1)
        query.setParameter("dId", dId);                  //...(2)
        query.setParameter("remarks", remarks);          //...(2)
        
        return query.getResultList();                    //...(3)
    }
}

ソースコード解説

番号 説明
(1) エンティティマネージャの「createNamedQuery」メソッドを使用して、Entityクラスに記述したSQL文を読み込む。引数はEntityクラスでSQL文につけた名前を指定する。
(2) SQL文中の変数に対して値を設定している。
(3) SQL文を実行し、結果を呼び出し元に返却している。

4.Logic層・Api層・index.htmlを編集する
手順3で追加したメソッドが呼び出される様に、Logic層・Api層クラスおよびindex.htmlファイルを編集する。
詳細は割愛する。

Enjoy Programing!!


<関連記事>
REST風サービスをJavaEEで構築する方法01(導入編)
REST風サービスをJavaEEで構築する方法02(雛形プロジェクト編)
REST風サービスをJavaEEで構築する方法03(RESTクライアント編)
REST風サービスをJavaEEで構築する方法04(各メソッド編)
REST風サービスをJavaEEで構築する方法05(パラメータの受け取り編)
REST風サービスをJavaEEで構築する方法06(JSON返却編1)
REST風サービスをJavaEEで構築する方法07(JSON返却編2)
REST風サービスをJavaEEで構築する方法08(Logic層編)
REST風サービスをJavaEEで構築する方法09(DB接続設定編)
REST風サービスをJavaEEで構築する方法10(DAO層編1)
REST風サービスをJavaEEで構築する方法11(DAO層編2)
・REST風サービスをJavaEEで構築する方法12(DAO層編3)[本記事]
REST風サービスをJavaEEで構築する方法13(SQLログ編)


<お勧め書籍>

わかりやすいJavaEEウェブシステム入門
JavaEEに関して基本的なことが分かり易く記述されている。
JavaEEに関する最初の1冊としてお勧めである。
Beginning Java EE 6 GlassFish 3で始めるエンタープライズJava
「金魚本」の愛称を持つJavaEEの教科書的な書籍である。
JavaEEを腰を据えて学びたい人にお勧めする1冊!!