こんにちは。スタルヒンです。
本日はJava言語のなかでよくJPQLがわからないと聞きますので
基本的な意味合いを説明し致します。
皆さんの参考になれば良いかなと思い書きましたのでご活用くださいね。
はじめに
皆さんは、JPAはなぜ作成されてかご存じですか?MicrosoftのLinqと同様な発想です。JDBCのように”SELECT * FROM テーブル名”などのSQL文字列をデータベースに渡して構文解析を行っていただいて、次々にデータを受けといったり環境をCloseしたりと大変な作業で実行してみないとSQLが正しいかどうか半弟できない点が問題です。ORマッピングという言葉は知ってますか?テーブルとオブジェクトをマッピングしてくれる点もコーディング量を少なくし、コーディング時にエラーとなってくれる即時性を行ってくれるものがJSPなのです。覚えてしまえば、開発効率は一目瞭然なのです。私から見れば涙が出るぐらい楽なコーディングなのです。
JPAといっても、あくまでも永続化管理のためのAPI仕様なので、実際はJPAの参照実装である、Hibernate、EclipseLinkを使って行います。
サンプルモデル
では、早速初めていきましょう。
説明していくにあたり、以下のテーブルを使っていきます。
m_user:ユーザマスタ | ||
id | ユーザID | PK |
name | 氏名 | |
age | 年齢 | |
birthday | 誕生日 | |
company_id | 会社 | FK |
m_company:会社マスタ | ||
id | 会社ID | PK |
name | 勤務先名 | |
address | 住所 | |
tel_no | 電話番号 |
準備編
エンティティを作成しよう
まず、上記で定義したテーブルのエンティティを作成します。
ユーザマスタのエンティティ
@Table(name="m_user")
@Entitypublic
class User{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private Integer age;
~getter/setter~
}
@ マークがついているものがいくつか存在しますが、これをアノテーションと呼びます。
そのアノテーションについて、いくつか説明していきます。
1行目: @Table(name=”テーブル名”)
エンティティ名と実テーブル名の名前が異なる場合のみ定義が必要にになります。
今回の場合、エンティティが「User」でテーブル名が「m_user」なので定義してあります。(Campanyも同様)
2行目: @Entity
必ず指定が必要です。これはJPA開始を意味します
4行目: @Id
エンティティクラス内のフィールドのいずれかに指定する必要があります。
5行目: @GeneratedValue(strategy = GenerationType.IDENTITY)
@Id が指定されたフィールドの値の採番方式を指定します。これを指定しておくことで、自分でIDをセットして登録という手間がなくなります。
会社マスタのエンティティ
@Table(name="m_company")
@Entitypublic
class Campany{
@Id
private Integer id;
private String name;
private String address;
@Column(name="tel_no")
private String telNo;
~getter/setter~
}
11行目: @Column(name=”カラム名”)
@Table と同様、フィールド名とカラム名が異なる場合のみ定義します。
エンティティの定義方法や、アノテーションについて述べましたが、実はアノテーションを定義する上でいくつかの条件あるので、ここでまとめたいと思います。・クラスに@Entityが定義されていること。
・クラス内のフィールドのいずれかに@Idが定義されていること。
・引数なしのコンストラクタを持つこと。
* 引数ありのコンストラクタを定義した場合は、明示的に引数なしのコンストラクタも定義が必要。
・フィールドをカプセル化(privateのフィールド、getter、setter)すること。
・final修飾子をクラスやフィールドに使わないこと。
次は作成したエンティティを使って、CRUD処理についてみていきましょう。
検索編
ユーザのデータを全件取得したい
// EntityManagerのFactoryクラスをPersistence.xmlで定義したユニット名を使って生成
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ユニット名");
// EntityManagerの生成
EntityManager em = emf.createEntityManager();
// クエリの生成
TypedQuery q = em.createQuery("SELECT u FROM User u",User.class); // 抽出
return q.getResultList();
SQLみたいな記述がありますが、これはSQLではなくJPQL(Java Persistence Query Language)と呼ばれるクエリ使って取得します。JPQLを使うことで、オブジェクトとして扱うことができます。もちろんSQLで記述することも可能です。
その場合はcreateNativeQueryメソッドを使いましょう。
ユーザのデータの中でキー(id)が一致するデータを取得したい
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ユニット名");
EntityManager em = emf.createEntityManager(); Users user = em.find(User.class,id);
EntityManagerのメソッドに「find」というメソッドがあるので、これを使います。
第2引数で指定できるのは、 @Id が指定されているフィールドの値のみです。
ユーザの中で年齢が30以上のデータを取得したい
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ユニット名");
EntityManager em = emf.createEntityManager(); List users = em.createQuery("SELECT u FROM User u WHERE u.age >= 30").getResultList();
@Id が指定されているフィールド以外で、条件を設定したい場合はcreateQueryを使います。
JPQLの記述でWHERE句を書いて、必要な条件を書きます。
結合編
関連テーブルを結合して取得する方法は、前に述べた検索処理とほぼ同じです。異なるのはエンティティクラスに定義するアノテーションです。アノテーションをつけることで、結合を意識することなく取得することができます。
ユーザ情報を取得する際に会社情報も取得したい
Userエンティティクラスに、Companyエンティティクラスのフィールドを定義します。
@Table(name="m_user")
@Entitypublic
class User{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private Integer age;
@ManyToOne
private Company campany;
~getter/setter~
}
関連するエンティティクラスをフィールドとして定義します。関連元テーブル(今回の場合User)から見た関連先テーブル(Campany)の関連がN対1なので、アノテーションに @ManyToOne を定義します。
これで、Userの検索処理したときに、Campanyも取得できます。
ユーザごとの会社情報を取得する場合は以下のようにします。
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ユニット名");
EntityManager em = emf.createEntityManager();
TypedQuery q = em.createQuery("SELECT u FROM User u",User.class);
ListuserList = q.getResultList();
for(User user : userList){
// 勤務地情報取得
Campany campany= user.getCompany(); }
ある勤務地に所属するユーザを取得したい
CampanyエンティティクラスにUserのエンティティクラスを定義します。
@Table(name="m_campany")
@Entitypublic
class Campany{
@Id
private Integer id;
private String name;
private String address;
@Column(name="tel_no")
private String telNo;
@OneToMany(mappedBy="campany")
private List userList;
~getter/setter~
}
関連元テーブル(今回の場合Campany)から見た関連先テーブル(User)の関連が1対Nなので、アノテーションに @OneToMany を定義します。あと、ここで注意してほしいのが、双方向に関連アノテーションを定義した場合、 @OneToMany を定義した方に「mappedBy」を定義する必要があります。
mappedByに指定する内容は、関連先エンティティクラス内に定義している関連元エンティティクラスのフィールド名を定義します。
取得した勤務地情報からユーザ情報を取得する場合は以下のようにします。
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ユニット名");
EntityManager em = emf.createEntityManager();
Campany campany= em.find(Campany.class,1); // ユーザ情報取得 List userList = campany.getUserList();
データ更新編
ユーザのデータを新規登録したい
EntityManagerFactory emf = Persistence.createEntityManagerFactory(“ユニット名”);
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction(); tx.begin(); // 勤務地情報取得Campany campany= em.find(Campany.class,1); // 登録するユーザ情報Use
r user = new User();user.setName(“デーコム”);user.setAge(30);user.setCampany(campany); // 登録em.persist(user); tx.commit();
新規で作成したエンティティを登録する場合は「persist」を使います。
あるユーザの勤務地を変更したい
EntityManagerFactory emf = Persistence.createEntityManagerFactory(“ユニット名”);
EntityManager em = emf.createEntityManager(); EntityTransaction tx = em.getTransaction();
tx.begin(); // 変更先の勤務地情報を取得Campany campany= entityManager.find(Campany.class,2); // 更新対象のユーザ情報取得
User user = em.find(User.class,1); // 変更先の勤務地をセットuser.seCampany(campany); // 更新em.merge(user); tx.commit;
変更したエンティティで更新する場合は「merge」を使います。
あるユーザを削除したい
EntityManagerFactory emf = Persistence.createEntityManagerFactory(“ユニット名”);
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin(); // 削除対象のユーザ情報取得User user = em.find(User.class,1); // 削除em.remove(user);
tx.commit;
対象エンティティを削除する場合は「remove」を使います。
まとめ
JPAでデータベース処理を行う際は、EntityManagerを使って行います。EntityManagerが持つ、今回利用したメソッドは以下のとおりです。
検索 | find |
登録 | persist |
更新 | merge |
削除 | remove |
今回はEntityManagerの簡単な使い方をメインにお話しました