JPA ( Java Persistence Annotation )は、オブジェクト指向ドメインモデルとリレーショナルデータベースシステムの間のギャップを埋めるためのJavaの標準ソリューションです。アイデアは、Javaクラスをリレーショナルテーブルにマップし、それらのクラスのプロパティをテーブルの行にマップすることです。これにより、同じプログラミングパラダイム内で2つの異なるテクノロジーをシームレスに連携させることにより、Javaコーディングの全体的なエクスペリエンスのセマンティクスが変更されます。この記事では、Javaでの概要とそのサポート実装について説明します。
概要
リレーショナルデータベースは、コンピューティングに関連するすべての複雑さではなく、コンピューティングで利用可能なすべての永続化テクノロジの中でおそらく最も安定しています。これは、いわゆる「ビッグデータ」の時代にあっても、「NoSQL」リレーショナルデータベースの需要と繁栄が一貫しているためです。リレーショナルデータベースは、単なる言葉ではなく、長年にわたる存在によって安定したテクノロジーです。 NoSQLは、企業内で大量の構造化データを処理するのに適している場合がありますが、多数のトランザクションワークロードは、リレーショナルデータベースを介してより適切に処理されます。また、リレーショナルデータベースに関連する優れた分析ツールがいくつかあります。
リレーショナルデータベースと通信するために、ANSIは SQLと呼ばれる言語を標準化しました。 (構造化照会言語 )。この言語で記述されたステートメントは、データの定義と操作の両方に使用できます。ただし、Javaを処理する際のSQLの問題は、構文構造が一致せず、コアが大きく異なることです。つまり、SQLは手続き型であるのに対し、Javaはオブジェクト指向です。そのため、Javaがオブジェクト指向で話すことができ、リレーショナルデータベースが相互に理解できるような実用的なソリューションが求められています。 JPAはその呼びかけに対する答えであり、2つの間に実用的なソリューションを確立するためのメカニズムを提供します。
オブジェクトマッピングとの関係
Javaプログラムは、 JDBCを使用してリレーショナルデータベースと対話します。 (Javaデータベースコネクティビティ )API。 JDBCドライバーは接続の鍵であり、JavaプログラムがJDBCAPIを使用してそのデータベースを操作できるようにします。接続が確立されると、Javaプログラムは文字列の形式でSQLクエリを実行します。 ■作成、挿入、更新、および削除操作を伝達します。これはすべての実用的な目的には十分ですが、Javaプログラマーの観点からは不便です。リレーショナルテーブルの構造を純粋なJavaクラスに改造して、通常のオブジェクト指向の方法でそれらを処理できるとしたらどうでしょうか。リレーショナルテーブルの構造は、表形式のデータの論理表現です。テーブルはエンティティ属性を説明する列で構成され、行はエンティティのコレクションです。たとえば、EMPLOYEEテーブルには、属性を持つ次のエンティティが含まれている場合があります。
Emp_number | 名前 | dept_no | 給与 | 場所 |
112233 | ピーター | 123 | 1200 | LA |
112244 | レイ | 234 | 1300 | NY |
112255 | サンディップ | 123 | 1400 | NJ |
112266 | カルパナ | 234 | 1100 | LA |
行は、テーブル内の主キー(emp_number)によって一意です。これにより、クイック検索が可能になります。テーブルは、別のテーブルの同等の行に関連する外部キー(dept_no)などのキーによって1つ以上のテーブルに関連付けられる場合があります。
Java Persistence 2.1仕様に従って、JPAは、スキーマ生成、型変換メソッド、クエリと検索操作でのエンティティグラフの使用、非同期永続コンテキスト、ストアドプロシージャの呼び出し、エンティティリスナークラスへの挿入のサポートを追加します。また、Java Persistenceクエリ言語、Criteria API、およびネイティブクエリのマッピングの機能強化も含まれています。
つまり、リレーショナルデータベースを処理する際に手続き的な部分がなく、すべてがオブジェクト指向であるという幻想を提供するためにすべてを行います。
JPAの実装
JPAは、Javaアプリケーションでのリレーショナルデータ管理について説明しています。これは仕様であり、多くの実装があります。一般的な実装には、Hibernate、EclipseLink、およびApacheOpenJPAがあります。 JPAは、JavaクラスのアノテーションまたはXML構成ファイルを介してメタデータを定義します。ただし、XMLとアノテーションの両方を使用してメタデータを記述することができます。このような場合、XML構成は注釈をオーバーライドします。アノテーションはJavaコードで記述されているのに対し、XML構成ファイルはJavaコードの外部にあるため、これは合理的です。したがって、後で、もしあれば、メタデータに変更を加える必要があります。アノテーションベースの構成の場合、Javaコードに直接アクセスする必要があります。これは常に可能であるとは限りません。このような場合、元のコードを変更することなく、新しいメタデータ構成または変更されたメタデータ構成をXMLファイルに書き込むことができ、それでも目的の効果が得られます。これは、XML構成を使用する利点です。ただし、注釈ベースの構成の方が使いやすく、プログラマーの間で人気があります。
- 休止状態 Red Hatにより、すべてのJPA実装の中で人気があり、最も進んでいます。 JPA実装に加えて使用できる独自の調整と追加機能を使用します。ユーザーのコミュニティが大きく、十分に文書化されています。追加の独自機能のいくつかは、マルチテナンシーのサポート、クエリでの関連付けられていないエンティティの結合、タイムスタンプ管理などです。
- EclipseLink TopLinkに基づいており、JPAバージョンのリファレンス実装です。マルチテナンシーからのサポート、データベース変更イベントの処理など、いくつかの興味深い独自機能とは別に、標準のJPA機能を提供します。
JavaSEプログラムでのJPAの使用
JavaプログラムでJPAを使用するには、HibernateやEclipseLinkなどのJPAプロバイダー、またはその他のライブラリが必要です。また、特定のリレーショナルデータベースに接続するJDBCドライバーが必要です。たとえば、次のコードでは、次のライブラリを使用しています。
- プロバイダー: EclipseLink
- JDBCドライバー: MySQL用JDBCドライバー(Connector / J)
次のEER図に示すように、2つのテーブル(従業員と部門)間の関係を1対1および1対多として確立します(図1を参照)。
図1: テーブルの関係
従業員 テーブルは、次のようにアノテーションを使用してエンティティクラスにマップされます。
package org.mano.jpademoapp; import javax.persistence.*; @Entity @Table(name = "employee") public class Employee { @Id private int id; private String name; private String phone; private String email; @OneToOne private Department department; public Employee() { super(); } public Employee(int id, String name, String phone, String email) { super(); this.id = id; this.name = name; this.phone = phone; this.email = email; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } }
そして、部門 テーブルは次のようにエンティティクラスにマップされます:
package org.mano.jpademoapp; import java.util.*; import javax.persistence.*; @Entity @Table(name = "department") public class Department { @Id private int id; private String location; @OneToMany private List<Employee> employees = new ArrayList<>(); public Department() { super(); } public Department(int id, String location) { super(); this.id = id; this.location = location; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public List<Employee> getEmployees() { return employees; } public void setEmployees(List<Employee> employees) { this.employees = employees; } }
構成ファイルpersistence.xml 、 META-INFで作成されます ディレクトリ。このファイルには、使用するJDBCドライバー、データベースアクセス用のユーザー名とパスワード、およびデータベース接続を確立するためにJPAプロバイダーが必要とするその他の関連情報などの接続構成が含まれています。
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" 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="JPADemoProject" transaction-type="RESOURCE_LOCAL"> <class>org.mano.jpademoapp.Employee</class> <class>org.mano.jpademoapp.Department</class> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/testdb" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="secret" /> <property name="javax.persistence.schema-generation .database.action" value="drop-and-create"/> <property name="javax.persistence.schema-generation .scripts.action" value="drop-and-create"/> <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/> </properties> </persistence-unit> </persistence>
エンティティは存続しません。エンティティを操作して永続的なライフサイクルを管理するには、ロジックを適用する必要があります。 EntityManager JPAが提供するインターフェースにより、アプリケーションはリレーショナルデータベース内のエンティティを管理および検索できます。 EntityManagerを使用してクエリオブジェクトを作成します データベースと通信します。 EntityManagerを取得するには 特定のデータベースに対して、 EntityManagerFactoryを実装するオブジェクトを使用します インターフェース。 静的があります createEntityManagerFactoryと呼ばれるメソッド 、永続性 EntityManagerFactoryを返すクラス 文字列として指定された永続性ユニットの場合 口論。次の基本的な実装では、ロジックを実装しました。
package org.mano.jpademoapp; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public enum PersistenceManager { INSTANCE; private EntityManagerFactory emf; private PersistenceManager() { emf=Persistence.createEntityManagerFactory("JPADemoProject"); } public EntityManager getEntityManager() { return emf.createEntityManager(); } public void close() { emf.close(); } }
これで、アプリケーションのメインインターフェイスを作成する準備が整いました。ここでは、単純さとスペースの制約のために、挿入操作のみを実装しました。
package org.mano.jpademoapp; import javax.persistence.EntityManager; public class Main { public static void main(String[] args) { Department d1=new Department(11, "NY"); Department d2=new Department(22, "LA"); Employee e1=new Employee(111, "Peter", "9876543210", "[email protected]"); Employee e2=new Employee(222, "Ronin", "993875630", "[email protected]"); Employee e3=new Employee(333, "Kalpana", "9876927410", "[email protected]"); Employee e4=new Employee(444, "Marc", "989374510", "[email protected]"); Employee e5=new Employee(555, "Anik", "987738750", "[email protected]"); d1.getEmployees().add(e1); d1.getEmployees().add(e3); d1.getEmployees().add(e4); d2.getEmployees().add(e2); d2.getEmployees().add(e5); EntityManager em=PersistenceManager .INSTANCE.getEntityManager(); em.getTransaction().begin(); em.persist(e1); em.persist(e2); em.persist(e3); em.persist(e4); em.persist(e5); em.persist(d1); em.persist(d2); em.getTransaction().commit(); em.close(); PersistenceManager.INSTANCE.close(); } }
注: 上記のコードで使用されているAPIの詳細については、適切なJavaAPIドキュメントを参照してください。 |
結論
明らかなように、JPAと永続性のコンテキストのコア用語は、ここで示した一瞥よりも広大ですが、簡単な概要から始める方が、長く複雑なダーティコードとその概念の詳細よりも優れています。コアJDBCのプログラミング経験が少しあれば、JPAがいかにあなたの生活をよりシンプルにすることができるかを間違いなく理解するでしょう。今後の記事に沿って、JPAについて徐々に深く掘り下げていきます。