ネイティブな日本語でのパラフレーズ例:Hibernate Named Queryの利用例 – @NamedQuery
ようこそ、Hibernate Named Queryのチュートリアルへ。HQLとNative SQL Queryの使用方法を見てきました。もし多くのクエリがある場合、それらはプロジェクト全体に散らばってしまい、コードの散乱を引き起こす可能性があります。そこでHibernateでは、クエリを中央の場所で定義し、コードのどこでも使用できるNamed Queryを提供しています。HQLとNative SQLの両方に対してNamed Queryを作成することができます。
ネイティブの日本語で以下を言い換える(1つのオプションのみ必要):
ハイバネートの名前付きクエリ
ハイバネイトの名前付きクエリは、ハイバネイトのマッピングファイルで定義することもできますし、JPAアノテーションの@NamedQueryと@NamedNativeQueryを使用して定義することもできます。今日は、それらの両方と、シンプルなアプリケーションでハイバネイトの名前付きクエリを使用する方法を説明します。HQLの例と同じデータベーステーブルを使用しますので、データベースのセットアップSQLスクリプトは、その投稿をチェックしてください。私たちのハイバネイト名前付きクエリの例プロジェクトでは、ハイバネイトのマッピングにはアノテーションを使用します。ただし、マッピングファイルとエンティティBeanクラスの両方で名前付きクエリを作成します。最終的なプロジェクトの構造は、以下の画像のようになります。主にハイバネイトの名前付きクエリに関連するコンポーネントに焦点を当てます。
ネイティブの日本語で以下を言い換えてください。オプションは一つだけ必要です。
「Hibernateの設定XML」
ネイティブな日本語で以下の文を言い換えてください、オプションは一つです:
「hibernate.cfg.xml」
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration SYSTEM "https://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">scdev123</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/TestDB</property>
<property name="hibernate.connection.username">scdev</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<mapping class="com.scdev.hibernate.model.Employee" />
<mapping class="com.scdev.hibernate.model.Address" />
<mapping resource="named-queries.hbm.xml" />
</session-factory>
</hibernate-configuration>
Hibernateの名前付きクエリXML
私たちは、HQLの名前付きクエリとネイティブSQLの名前付きクエリだけを含む、ヒベルネイトのマッピングファイル「named-queries.hbm.xml」を持っています。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"https://hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<query name="HQL_GET_ALL_EMPLOYEE">from Employee</query>
<query name="HQL_GET_EMPLOYEE_BY_ID">
<![CDATA[from Employee where emp_id = :id]]>
</query>
<query name="HQL_GET_EMPLOYEE_BY_SALARY">
<![CDATA[from Employee where emp_salary > :salary]]>
</query>
<sql-query name="SQL_GET_ALL_EMPLOYEE">
<![CDATA[select emp_id, emp_name, emp_salary from Employee]]>
</sql-query>
<sql-query name="SQL_GET_ALL_EMP_ADDRESS">
<![CDATA[select {e.*}, {a.*} from Employee e join Address a ON e.emp_id=a.emp_id]]>
<return alias="e" class="com.scdev.hibernate.model.Employee" />
<return-join alias="a" property="e.address"></return-join>
</sql-query>
</hibernate-mapping>
HQLの名前付きクエリにはquery要素を、ネイティブSQLの名前付きクエリにはsql-query要素を使用します。結果セットがマッピングされるエンティティを宣言するために、return要素を使用することができます。複数のテーブルの結合がある場合には、return-joinを使用します。マッピングのXMLファイルが壊れないように、Hibernateの名前付きクエリを宣言する際にはCDATAを使用する必要があります。そうしないと、<と>の記号がマッピングを乱す可能性があります。
ネイティブの日本語で以下を言い換えると、ヒベルネイト名前付きクエリ@NamedQueryアノテーションとなります。
私たちは2つのモデルクラス、”Employee”と”Address”を持っています。Addressクラスには、以下のように名前付きクエリを定義しています。
package com.scdev.hibernate.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
@Entity
@Table(name = "ADDRESS")
@NamedQueries({ @NamedQuery(name = "@HQL_GET_ALL_ADDRESS",
query = "from Address") })
@NamedNativeQueries({ @NamedNativeQuery(name = "@SQL_GET_ALL_ADDRESS",
query = "select emp_id, address_line1, city, zipcode from Address") })
public class Address {
@Id
@Column(name = "emp_id", unique = true, nullable = false)
@GeneratedValue(generator = "gen")
@GenericGenerator(name = "gen", strategy = "foreign", parameters = { @Parameter(name = "property", value = "employee") })
private long id;
@Column(name = "address_line1")
private String addressLine1;
@Column(name = "zipcode")
private String zipcode;
@Column(name = "city")
private String city;
@OneToOne
@PrimaryKeyJoinColumn
private Employee employee;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
@Override
public String toString() {
return "AddressLine1= " + addressLine1 + ", City=" + city
+ ", Zipcode=" + zipcode;
}
}
ネイティブな日本語で以下を言い換えます。1つのオプションだけを使用します:
HibernateのNamed Queryテストプログラム
上記で定義されたすべてのHibernateの名前付きクエリを使用するためのテストプログラムを作成しましょう。
package com.scdev.hibernate.main;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.scdev.hibernate.model.Address;
import com.scdev.hibernate.model.Employee;
import com.scdev.hibernate.util.HibernateUtil;
public class HibernateNamedQueryExample {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
// Prep work
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
//HQL Named Query Example
Query query = session.getNamedQuery("HQL_GET_ALL_EMPLOYEE");
List<Employee> empList = query.list();
for (Employee emp : empList) {
System.out.println("List of Employees::" + emp.getId() + ","
+ emp.getAddress().getCity());
}
query = session.getNamedQuery("HQL_GET_EMPLOYEE_BY_ID");
query.setInteger("id", 2);
Employee emp = (Employee) query.uniqueResult();
System.out.println("Employee Name=" + emp.getName() + ", City="
+ emp.getAddress().getCity());
query = session.getNamedQuery("HQL_GET_EMPLOYEE_BY_SALARY");
query.setInteger("salary", 200);
empList = query.list();
for (Employee emp1 : empList) {
System.out.println("List of Employees::" + emp1.getId() + ","
+ emp1.getSalary());
}
query = session.getNamedQuery("@HQL_GET_ALL_ADDRESS");
List<Address> addressList = query.list();
for (Address addr : addressList) {
System.out.println("List of Address::" + addr.getId() + "::"
+ addr.getZipcode() + "::" + addr.getEmployee().getName());
}
//Native SQL Named Query Example
query = session.getNamedQuery("@SQL_GET_ALL_ADDRESS");
List<Object[]> addressObjArray = query.list();
for(Object[] row : addressObjArray){
for(Object obj : row){
System.out.print(obj + "::");
}
System.out.println("\n");
}
query = session.getNamedQuery("SQL_GET_ALL_EMP_ADDRESS");
addressObjArray = query.list();
for(Object[] row : addressObjArray){
Employee e = (Employee) row[0];
System.out.println("Employee Info::"+e);
Address a = (Address) row[1];
System.out.println("Address Info::"+a);
}
// rolling back to save the test data
tx.commit();
// closing hibernate resources
sessionFactory.close();
}
}
上記のプログラムをテストデータで実行すると、以下の出力が生成されます。
Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_
Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
List of Employees::1,San Jose
List of Employees::2,Santa Clara
List of Employees::3,Bangalore
List of Employees::4,New Delhi
Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_ where emp_id=?
Employee Name=David, City=Santa Clara
Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_ where emp_salary>?
List of Employees::3,300.0
List of Employees::4,400.0
Hibernate: select address0_.emp_id as emp_id1_0_, address0_.address_line1 as address_2_0_, address0_.city as city3_0_, address0_.zipcode as zipcode4_0_ from ADDRESS address0_
List of Address::1::95129::Pankaj
List of Address::2::95051::David
List of Address::3::560100::Lisa
List of Address::4::100100::Jack
Hibernate: select emp_id, address_line1, city, zipcode from Address
1::Albany Dr::San Jose::95129::
2::Arques Ave::Santa Clara::95051::
3::BTM 1st Stage::Bangalore::560100::
4::City Centre::New Delhi::100100::
Hibernate: select e.emp_id as emp_id1_1_0_, e.emp_name as emp_name2_1_0_, e.emp_salary as emp_sala3_1_0_, a.emp_id as emp_id1_0_1_, a.address_line1 as address_2_0_1_, a.city as city3_0_1_, a.zipcode as zipcode4_0_1_ from Employee e join Address a ON e.emp_id=a.emp_id
Employee Info::Id= 1, Name= Pankaj, Salary= 100.0, {Address= AddressLine1= Albany Dr, City=San Jose, Zipcode=95129}
Address Info::AddressLine1= Albany Dr, City=San Jose, Zipcode=95129
Employee Info::Id= 2, Name= David, Salary= 200.0, {Address= AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051}
Address Info::AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051
Employee Info::Id= 3, Name= Lisa, Salary= 300.0, {Address= AddressLine1= BTM 1st Stage, City=Bangalore, Zipcode=560100}
Address Info::AddressLine1= BTM 1st Stage, City=Bangalore, Zipcode=560100
Employee Info::Id= 4, Name= Jack, Salary= 400.0, {Address= AddressLine1= City Centre, City=New Delhi, Zipcode=100100}
Address Info::AddressLine1= City Centre, City=New Delhi, Zipcode=100100
ネイティブな日本語で以下の文を言い換えましょう。1つのオプションで結構です。
Hibernate名前付きクエリの重要なポイント
ハイバネート名前付きクエリについての注目すべきポイントはいくつかあります。
-
- ネイティブな日本語で言い換えると、次のようになります:
HibernateのNamed Queryは、コード全体に散らばらせるのではなく、中央の場所でクエリをグループ化するために役立ちます。
HibernateのNamed Queryの構文は、Hibernateセッションファクトリが作成された時にチェックされるため、名前付きクエリにエラーがある場合にアプリケーションが速やかにエラーとなります。
HibernateのNamed Queryはグローバルであり、一度定義すればアプリケーション全体で使用することができます。
Named Queryの主なデメリットの1つは、定義された場所を見つける必要があるため、デバッグが困難であることです。
HibernateのNamed Queryの例は以上です。サンプルプロジェクトは以下のリンクからダウンロードできます。
ヒベルネートの名前付きクエリプロジェクトをダウンロードしてください。