Jpa-jpql
JPA-JPQL
この章では、JPQLと、それが永続性ユニットでどのように機能するかについて説明します。 この章では、例は前の章で使用したものと同じパッケージ階層に従います。
Java Persistence Query言語
JPQLは、JPA仕様で定義されているJava Persistence Query Languageです。 エンティティに対するクエリを作成して、リレーショナルデータベースに格納するために使用されます。 JPQLは、SQL構文に基づいて開発されています。 ただし、データベースには直接影響しません。
JPQLは、SELECT句を使用して情報またはデータを取得でき、UPDATE句とDELETE句を使用して一括更新を実行できます。 EntityManager.createQuery()APIは、言語のクエリをサポートします。
クエリ構造
JPQL構文は、SQLの構文に非常によく似ています。 SQLは単純な構造化照会言語であり、多くの開発者がアプリケーションで使用しているため、SQLのような構文を持つことは利点です。 SQLはリレーショナルデータベースのテーブル、レコード、およびフィールドに対して直接機能しますが、JPQLはJavaクラスおよびインスタンスに対して機能します。
たとえば、JPQLクエリは、SQLの場合のように、データベースからフィールド結果セットではなくエンティティオブジェクトを取得できます。 JPQLクエリ構造は次のとおりです。
SELECT ... FROM ...
[WHERE ...]
[GROUP BY ... [HAVING ...]]
[ORDER BY ...]
JPQLのDELETEおよびUPDATEクエリの構造は、次のように単純です。
DELETE FROM ... [WHERE ...]
UPDATE ... SET ... [WHERE ...]
スカラー関数と集計関数
スカラー関数は、入力値に基づいて結果値を返します。 集計関数は、入力値を計算して結果の値を返します。
前の章で使用したのと同じ従業員管理の例に従ってください。 ここでは、JPQLのスカラー関数と集計関数を使用してサービスクラスを調べます。
jpadb.employeeテーブルに次のレコードが含まれていると仮定しましょう。
Eid | Ename | Salary | Deg |
---|---|---|---|
1201 | Gopal | 40000 | Technical Manager |
1202 | Manisha | 40000 | Proof Reader |
1203 | Masthanvali | 40000 | Technical Writer |
1204 | Satish | 30000 | Technical Writer |
1205 | Krishna | 30000 | Technical Writer |
1206 | Kiran | 35000 | Proof Reader |
次のように、 com.finddevguides.eclipselink.service パッケージの下に ScalarandAggregateFunctions.java という名前のクラスを作成します。
package com.finddevguides.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class ScalarandAggregateFunctions {
public static void main( String[ ] args ) {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.createEntityManager();
//Scalar function
Query query = entitymanager.
createQuery("Select UPPER(e.ename) from Employee e");
List<String> list = query.getResultList();
for(String e:list) {
System.out.println("Employee NAME :"+e);
}
//Aggregate function
Query query1 = entitymanager.createQuery("Select MAX(e.salary) from Employee e");
Double result = (Double) query1.getSingleResult();
System.out.println("Max Employee Salary :" + result);
}
}
上記のプログラムをコンパイルして実行すると、次のようにEclipse IDEのコンソールパネルに出力が表示されます。
Employee NAME :GOPAL
Employee NAME :MANISHA
Employee NAME :MASTHANVALI
Employee NAME :SATISH
Employee NAME :KRISHNA
Employee NAME :KIRAN
ax Employee Salary :40000.0
Between、And、Likeキーワード
「間」、「そして」、「いいね」はJPQLの主要なキーワードです。 これらのキーワードは、クエリのWhere句の後に使用されます。
次のように、 com.finddevguides.eclipselink.service パッケージの下に BetweenAndLikeFunctions.java という名前のクラスを作成します。
package com.finddevguides.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.finddevguides.eclipselink.entity.Employee;
public class BetweenAndLikeFunctions {
public static void main( String[ ] args ) {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.createEntityManager();
//Between
Query query = entitymanager.createQuery( "Select e " + "from Employee e " + "where e.salary " + "Between 30000 and 40000" );
List<Employee> list=(List<Employee>)query.getResultList( );
for( Employee e:list ){
System.out.print("Employee ID :" + e.getEid( ));
System.out.println("\t Employee salary :" + e.getSalary( ));
}
//Like
Query query1 = entitymanager.createQuery("Select e " + "from Employee e " + "where e.ename LIKE 'M%'");
List<Employee> list1=(List<Employee>)query1.getResultList( );
for( Employee e:list1 ) {
System.out.print("Employee ID :"+e.getEid( ));
System.out.println("\t Employee name :"+e.getEname( ));
}
}
}
上記のプログラムをコンパイルして実行すると、次のようにEclipse IDEのコンソールパネルに出力が表示されます。
Employee ID :1201 Employee salary :40000.0
Employee ID :1202 Employee salary :40000.0
Employee ID :1203 Employee salary :40000.0
Employee ID :1204 Employee salary :30000.0
Employee ID :1205 Employee salary :30000.0
Employee ID :1206 Employee salary :35000.0
Employee ID :1202 Employee name :Manisha
Employee ID :1203 Employee name :Masthanvali
ご注文
JPQLでレコードを並べ替えるには、ORDER BY句を使用します。 この句の使用法はSQLでの使用法と同じですが、エンティティを扱います。 例による順序に従ってください。
次のように com.finddevguides.eclipselink.service パッケージの下にクラスOrdering.javaを作成します。
package com.finddevguides.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.finddevguides.eclipselink.entity.Employee;
public class Ordering {
public static void main( String[ ] args ) {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.createEntityManager();
//Between
Query query = entitymanager.createQuery( "Select e " + "from Employee e " + "ORDER BY e.ename ASC" );
List<Employee> list = (List<Employee>)query.getResultList( );
for( Employee e:list ) {
System.out.print("Employee ID :" + e.getEid( ));
System.out.println("\t Employee Name :" + e.getEname( ));
}
}
}
上記のプログラムをコンパイルして実行すると、次のようにEclipse IDEのコンソールパネルに出力が表示されます。
Employee ID :1201 Employee Name :Gopal
Employee ID :1206 Employee Name :Kiran
Employee ID :1205 Employee Name :Krishna
Employee ID :1202 Employee Name :Manisha
Employee ID :1203 Employee Name :Masthanvali
Employee ID :1204 Employee Name :Satish
名前付きクエリ
@NamedQueryアノテーションは、定義済みの変更不可能なクエリ文字列を持つクエリとして定義されます。 動的なクエリの代わりに、名前付きクエリを使用すると、JPQLクエリ文字列をPOJOから分離することにより、コード編成を改善できます。 また、リテラルをクエリ文字列に動的に埋め込むのではなく、クエリパラメータを渡し、より効率的なクエリを実現します。
まず、次のように、* Name.Queryアノテーションを com.finddevguides.eclipselink.entity パッケージの Employee.java という名前のEmployeeエンティティクラスに追加します。
package com.finddevguides.eclipselink.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
@Entity
@Table
@NamedQuery(query = "Select e from Employee e where e.eid = :id", name = "find employee by id")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int eid;
private String ename;
private double salary;
private String deg;
public Employee(int eid, String ename, double salary, String deg) {
super( );
this.eid = eid;
this.ename = ename;
this.salary = salary;
this.deg = deg;
}
public Employee( ) {
super();
}
public int getEid( ) {
return eid;
}
public void setEid(int eid) {
this.eid = eid;
}
public String getEname( ) {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public double getSalary( ) {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getDeg( ) {
return deg;
}
public void setDeg(String deg) {
this.deg = deg;
}
@Override
public String toString() {
return "Employee [eid=" + eid + ", ename=" + ename + ", salary=" + salary + ", deg=" + deg + "]";
}
}
次のように、 com.finddevguides.eclipselink.service パッケージの下に NamedQueries.java という名前のクラスを作成します。
package com.finddevguides.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.finddevguides.eclipselink.entity.Employee;
public class NamedQueries {
public static void main( String[ ] args ) {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.createEntityManager();
Query query = entitymanager.createNamedQuery("find employee by id");
query.setParameter("id", 1204);
List<Employee> list = query.getResultList( );
for( Employee e:list ){
System.out.print("Employee ID :" + e.getEid( ));
System.out.println("\t Employee Name :" + e.getEname( ));
}
}
}
上記のプログラムをコンパイルして実行すると、次のようにEclipse IDEのコンソールパネルに出力が表示されます。
Employee ID :1204 Employee Name :Satish
上記のすべてのクラスを追加すると、パッケージ階層は次のように表示されます。
熱心で遅延読み込み
JPAの主な概念は、キャッシュメモリにデータベースの複製コピーを作成することです。 データベースとのトランザクション中、最初は重複データに影響し、エンティティマネージャーを使用してコミットされた場合にのみ、変更がデータベースに反映されます。
データベースからレコードを取得する方法には、熱心な取得と遅延取得の2つの方法があります。
熱心なフェッチ
主キーを使用してレコードを検索しながら、レコード全体を取得します。
遅延フェッチ
プライマリキーが存在する場合、通知の可用性をチェックします。 その後、そのエンティティのgetterメソッドのいずれかを呼び出すと、全体が取得されます。
ただし、初めてレコードをフェッチしようとすると、遅延フェッチが可能です。 これにより、レコード全体のコピーが既にキャッシュメモリに保存されます。 パフォーマンスに関しては、遅延フェッチが望ましいです。