Java JPA(Java Persistance API)

JPAJava Persistance API)ってなんぞや~?

JPAとはJavaの世界とリレーショナル・データベース(RDB)の世界を直接的に結ぶための仕組みです。「JavaのオブジェクトとRDB(レコード、テーブル)との間で自動変換を行う仕組み」がJPAだと理解していただけばよいでしょう。

初めてのJPA--シンプルで使いやすい、Java EEのデータ永続化機能の基本を学ぶ - builder by ZDNet Japan

ということらしいです。

JPAにも、種類があって

が代表的なのだそうです。

JPAの基礎1 - Qiita

今回は、EclipseLinkというものを使って、JPAを実装していきます。

JPAのイメージ図

f:id:ts0818:20170717131349p:plain

EntityManagerというオブジェクトを介して、データベースのテーブルとエンティティというクラスのオブジェクトを結びつけているようです。

EntityManagerの配下には、永続性コンテキストというエンティティの状態を表すオブジェクトも存在するようです。

JPAの特徴

Java Persistence APIJPA)とは、関係データベースのデータを扱う Java SE および Java EE のアプリケーションを開発するためのJavaフレームワークである。

JPA は、以下の3つの部分から成る。

  • API(javax.persistence パッケージで定義されている)
  • Java Persistence Query Language
  • オブジェクト/関係メタデータ

JPAリファレンス実装EclipseLinkとして実装されている。

Java Persistence API - Wikipedia 

JPAでできることは、 

  • Javaオブジェクトとデータベース・テーブルとの間の変換指定(マッピング指定)をアノテーションだけで行える
  • Javaオブジェクトを、そのまま読み書き/削除/検索することができる
  • オブジェクト指向の問い合わせ言語(JPQL:Java Persistence Query Language)を利用できる
  • JPQLと同等のAPIも使うことができる

のようなことのようです。 

EclipseJPAを使ってみる

Eclipseで、「ファイル」>「新規」>「その他」を選択。 

f:id:ts0818:20170717135815j:plain

JPA」>「JPAプロジェクト」を選択し、「次へ(N)>」をクリック。

f:id:ts0818:20170717135812j:plain

「プロジェクト名」と「ターゲット・ランタイム(U)」を指定して、「次へ(N)」をクリック。インストールしたJava SEのバージョンに合わせます。もしくは、Eclipseの「ウィンドウ」>「設定」>「Java」>「インストール済みのJRE」でチェックの付いているバージョンに合わせてもいけるかもしれません。

f:id:ts0818:20170717135809j:plain

デフォルトの状態で「次へ(N)」をクリック。

f:id:ts0818:20170717135806j:plain

「プラットフォーム(P)」で「EclipseLink ×.×.×」を選択し、「JPA実装」の「型:」を「ライブラリ構成を無効」にし「完了」。

f:id:ts0818:20170717135801j:plain

パースペクティブ」が「JPA」になってない場合は、「パースペクティブ(R)」>「パースペクティブを開く(O)...」>「その他(O)...」を選択。

f:id:ts0818:20170717140926j:plain

JPA」を選択し、「OK」。

f:id:ts0818:20170717140921j:plain

「データ・ソース・エクスプローラー」で「データベース接続」の上で右クリックし、「新規(N)...」をクリック。

f:id:ts0818:20170717140917j:plain

MySQL」を選択し、「次へ(N)」をクリック。

f:id:ts0818:20170717140912j:plain 

f:id:ts0818:20170717141457j:plainをクリックします。

f:id:ts0818:20170717140908j:plain

「使用可能なドライバー・テンプレート(A):」で「MySQL JDBCドライバー」にインストールしていたJDBCドライバーのバージョンを選択します。

f:id:ts0818:20170717141817j:plain

「Jarリスト」タブを選択し、「すべてクリア(C)」をクリック。 

f:id:ts0818:20170717141814j:plain

「Jar/Zip の追加(A)...」をクリック。

f:id:ts0818:20170717141811j:plain

インストールしていたJDBCドライバーを選択。

f:id:ts0818:20170717141802j:plain

「OK」をクリック。

f:id:ts0818:20170717141759j:plain

データベースの接続情報を入力し、「接続のテスト(T)」をクリック。 

f:id:ts0818:20170717142516j:plain

Ping が正常に完了しました」と表示されればOK。「完了」をクリック。

f:id:ts0818:20170717142523j:plain

「データ・ソース・エクスプローラー」 にデータベースが表示されていればOK。

f:id:ts0818:20170717142511j:plain

続いて、JPAプロジェクトにデータベース接続情報を設定していきます。

「プロジェクト・エクスプローラー」で作成していたプロジェクトを選択し、右クリック、「プロパティー」を選択。

f:id:ts0818:20170717143440j:plain

JPA」を選択し、「接続(C)」に「MySQL」を選択し、「OK」をクリック。

f:id:ts0818:20170717143435j:plain

続いて、EclipseLink JPAJDBCドライバをプロジェクトで使えるようにします。

まずは、EclipseLink JPAをインストールします。 

http://www.eclipse.org/eclipselink/ にアクセス。「Download」のリンクをクリック。

f:id:ts0818:20170717145059j:plain

「EclipseLink 2.6.4 Installer Zip」をクリック。

f:id:ts0818:20170717145053j:plain

もし、Downloadされず、次のようなページに遷移したら、「Download」をクリック。

f:id:ts0818:20170717145049j:plain

zipファイルがダウンロードされます。

f:id:ts0818:20170717145046j:plain

zipファイルを開くと、「eclipselink」というフォルダがあります。この中で、

f:id:ts0818:20170717145038j:plain

C:¥Users¥ユーザー名¥Downloads¥eclipselink-2.6.4.v20160829-44060b6.zip¥eclipselink¥jlib¥eclipselink.jarファイルと、

f:id:ts0818:20170717145522j:plain

C:¥Users¥ユーザー名¥Downloadseclipselink-2.6.4.v20160829-44060b6.zip¥eclipselink¥jlib¥jpa¥javax.persistence_2.1.1.v201509150925.jar

f:id:ts0818:20170717145519j:plain

の2つのファイルが必要になります。

  • eclipselink.jar
  • javax.persistence_2.1.1.v201509150925.jar

 Eclipseのpluginフォルダに元々入ってるのもあったけど....ドンマイ!

f:id:ts0818:20170717150601j:plain

zipファイルの中身は、一旦デスクトップなどに展開(解凍)しておきましょう。

2つのファイルを、ライブラリを格納している任意のフォルダに移動するらしいのですが、配置場所が分からないので、プロジェクト内にlibフォルダを作成し、その中に配置しました。

その後で、プロジェクトの上で右クリック「ビルド・パス(B)」「ビルド・パスの構成(C)...」を選択。

f:id:ts0818:20170717154306j:plain

 「外部JRA の追加(X)...」をクリック。

f:id:ts0818:20170717154201j:plain

配置した、2つのファイルを選択します。 

f:id:ts0818:20170717154151j:plain

f:id:ts0818:20170717154147j:plain

ファイルが追加されればOK。 

f:id:ts0818:20170717154141j:plain

「プロジェクト・エクスプローラー」の「参照ライブラリー」に追加されていればOK。

f:id:ts0818:20170717154137j:plain

JDBCドライバも使えるようにする必要があるので、同じく「ビルド・パス(B)」「ビルド・パスの構成(C)...」、「外部JRA の追加(X)...」の流れで追加しておきます。

f:id:ts0818:20170717173540j:plain

JDBCドライバが追加されればOK。

f:id:ts0818:20170717173536j:plain

「プロジェクト・エクスプローラー」の「参照ライブラリー」に追加されていればOK。

f:id:ts0818:20170717173818j:plain

 

 

続いて、接続情報をJPAプロジェクトの設定ファイル(persistence.xml)に設定していきます。

「プロジェクト・エクスプローラー」のプロジェクトの中の「src」>「META-INF」>「persistence.xml」をダブルクリック。「接続」タブを選択。

f:id:ts0818:20170717155129j:plain

下記のように設定していきます。 

項目名 設定値
トランザクション・タイプ: リソース・ローカル
ドライバー: com.mysql.jdbc.Driver
URL: jdbc:mysql://localhost:3306/sampledb
ユーザー root
パスワード root

f:id:ts0818:20170717183525j:plain

保存し、「ソース」タブを選択すると

<!--?xml version="1.0" encoding="UTF-8"?-->
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
	<persistence-unit name="SampleJPA" transaction-type="RESOURCE_LOCAL">
		<properties>
			<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"></property>
			<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/sampledb">
			<property name="javax.persistence.jdbc.user" value="root"></property>
			<property name="javax.persistence.jdbc.password" value="root"></property>
		</property></properties>
	</persistence-unit>
</persistence>

persistance.xmlファイルの内容が更新されています。

続いて、エンティティを作成していきます。

「プロジェクト・エクスプローラー」のプロジェクト名の上で右クリックし、「新規」>「JPAエンティティー」を選択。

f:id:ts0818:20170717162357j:plain

「クラス名(M):」を入力し、「次へ(N):」をクリック。(「Javaパッケージ(K):」も入力しておくと良いかもしれません。)

f:id:ts0818:20170717162354j:plain

「エンティティ名(M):」に、データベースのテーブルと一致するものを指定。「追加(A)...」で「エンティティ・フィールド」を設定。データベースのテーブルと合わせます。

f:id:ts0818:20170717162351j:plain

自分の場合、sampledbデータベースにemployeesテーブルを作っていました。 

f:id:ts0818:20170717163154j:plain

すべてのフィールドを追加出来たら、主キー(Primary Key)に該当するフィールドの「キー」にチェックを入れ、「完了(F)」をクリック。

f:id:ts0818:20170717162347j:plain

package sampleJpa;

import java.io.Serializable;
import java.lang.Integer;
import java.lang.String;
import javax.persistence.*;

/**
 * Entity implementation class for Entity: Employees
 *
 */
@Entity

public class Employees implements Serializable {

	   
	@Id
	private String code;
	private String name;
	private Integer age;
	private String section;
	private static final long serialVersionUID = 1L;

	public Employees() {
		super();
	}   
	public String getCode() {
		return this.code;
	}

	public void setCode(String code) {
		this.code = code;
	}   
	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}   
	public Integer getAge() {
		return this.age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}   
	public String getSection() {
		return this.section;
	}

	public void setSection(String section) {
		this.section = section;
	}
   
}

エンティティクラスが作成されます。

作成したエンティティを、JPAの管理対象とするため、設定ファイル(persistance.xml)に追加します。

「プロジェクト・エクスプローラー」のプロジェクト上で右クリックし、「JPAツール」 >「クラス・リストの同期化」をクリック。

f:id:ts0818:20170717164013j:plain

persistance.xmlファイルを確認すると、「<class>sampleJpa.Employees</class>」が追加されています。

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
	<persistence-unit name="SampleJPA" transaction-type="RESOURCE_LOCAL">
		<class>sampleJpa.Employees</class>
		<properties>
			<property name="javax.persistence.jdbc.driver" value="org.eclipse.persistence.platform.database.MySQLPlatform"/>
			<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/sampledb"/>
			<property name="javax.persistence.jdbc.user" value="root"/>
			<property name="javax.persistence.jdbc.password" value="root"/>
		</properties>
	</persistence-unit>
</persistence>

JPAを利用するための準備が整ったので、実行クラスを作っていきます。

 

package sampleJpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class SampleJPA {

  public static void main(String[] args) {
    // EntityManagerオブジェクトの生成
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("SampleJPA");
    EntityManager em = emf.createEntityManager();

    // トランザクションの開始
    EntityTransaction et = em.getTransaction();
    et.begin();

    // エンティティの生成
    Employees employees = new Employees();
    employees.setCode("201751");
    employees.setName("鈴木一郎");
    employees.setAge(43);
    employees.setSection("外野手");

    // テーブルへ格納
    em.persist(employees);

    // トランザクションの終了
    et.commit();

    // employeesテーブルからデータを抽出
    Employees result = em.find(Employees.class, "201751");
    System.out.println(result.getName());

    // EntityManagerを閉じる
    em.close();
    emf.close();

  }

}

実行結果

[EL Info]: 2017-07-17 17:53:10.983--ServerSession(1906335777)--EclipseLink, version: Eclipse Persistence Services - 2.6.4.v20160829-44060b6
Mon Jul 17 17:53:11 JST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
Mon Jul 17 17:53:11 JST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
[EL Info]: connection: 2017-07-17 17:53:11.245--ServerSession(1906335777)--/file:/C:/workspace/SampleJPA/build/classes/_SampleJPA login successful
鈴木一郎
[EL Info]: connection: 2017-07-17 17:53:11.296--ServerSession(1906335777)--/file:/C:/workspace/SampleJPA/build/classes/_SampleJPA logout successful

SSLを使っていないため警告は出ますが、実行できました。

実行前

f:id:ts0818:20170717175622j:plain 

実行後

f:id:ts0818:20170717175625j:plain

例外処理などは実装していないので、一度、INSERTされたら、DELETEで削除しとかないとエラーになってしまいます。

ちなみに、複数のエンティティを扱う場合は、「"総称型のスーパークラス"」を利用するのが良いようです。

package sampleJpa;

import javax.persistence.EntityManager;

public class Db<T> {
  private Class<T> cl;
  private EntityManager em;
  
  public Db(Class<T> cl) {
    this.cl = cl;
  }
  
  public void create(T obj) {
    this.em.persist(obj);
  }
  
  public void update(T obj) {
    this.em.merge(obj);
  }
  
  public T find(Object id) {
	 return em.find(cl, id); 
  }
  
  public void delete(T obj) {
	 this.em.remove(obj);  
  }
  
}

package sampleJpa;

public class EmployeesDb extends Db {
  public EmployeesDb() {
    super(Employees.class);
  }
}

実際に使う場合は、実装クラスで

package sampleJpa;

public class Main {

	public static void main(String[] args) {
		// 
		EmployeesDb employeeDb = new EmployeesDb();
		Employees employees = new Employees();

		employeeDb.create(employees);
	}

}

みたいに使っていくようです。JPAは導入までに一苦労な感がありますが、使いこなせるようになりたいものです。