Hibernate-クイックガイド
JDBCとは何ですか?
JDBCは Java Database Connectivity。これは、JavaプログラムからリレーショナルデータベースにアクセスするためのJavaAPIのセットを提供します。これらのJavaAPIを使用すると、JavaプログラムでSQLステートメントを実行し、SQL準拠のデータベースと対話できます。
JDBCは、さまざまなプラットフォームで実行でき、変更なしでさまざまなDBMSと対話できるデータベースに依存しないアプリケーションを作成するための柔軟なアーキテクチャを提供します。
JDBCの長所と短所
JDBCの長所 | JDBCの短所 |
---|---|
クリーンでシンプルなSQL処理 大量のデータで良好なパフォーマンス 小さなアプリケーションに非常に適しています シンプルな構文なので習得が簡単 |
大規模なプロジェクトで使用する場合は複雑 大きなプログラミングオーバーヘッド カプセル化なし MVCの概念を実装するのは難しい クエリはDBMS固有です |
なぜオブジェクトリレーショナルマッピング(ORM)なのか?
オブジェクト指向システムを使用する場合、オブジェクトモデルとリレーショナルデータベースの間に不一致があります。RDBMSはデータを表形式で表しますが、JavaやC#などのオブジェクト指向言語はデータをオブジェクトの相互接続されたグラフとして表します。
適切なコンストラクタと関連するパブリック関数を持つ次のJavaクラスを検討してください-
public class Employee {
private int id;
private String first_name;
private String last_name;
private int salary;
public Employee() {}
public Employee(String fname, String lname, int salary) {
this.first_name = fname;
this.last_name = lname;
this.salary = salary;
}
public int getId() {
return id;
}
public String getFirstName() {
return first_name;
}
public String getLastName() {
return last_name;
}
public int getSalary() {
return salary;
}
}
上記のオブジェクトが次のRDBMSテーブルに格納および取得されることを考慮してください-
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
最初の問題は、数ページまたはアプリケーションを開発した後でデータベースの設計を変更する必要がある場合はどうなるでしょうか。次に、オブジェクトをリレーショナルデータベースにロードして保存すると、次の5つの不一致の問題が発生します。
シニア番号 | 不一致と説明 |
---|---|
1 | Granularity データベース内の対応するテーブルの数よりも多くのクラスを持つオブジェクトモデルがある場合があります。 |
2 | Inheritance RDBMSは、オブジェクト指向プログラミング言語の自然なパラダイムである継承に似たものを定義していません。 |
3 | Identity RDBMSは、「同一性」の概念を1つだけ定義します。それは主キーです。ただし、Javaは、オブジェクトの同一性(a == b)とオブジェクトの同等性(a.equals(b))の両方を定義します。 |
4 | Associations オブジェクト指向言語はオブジェクト参照を使用して関連付けを表しますが、RDBMSは関連付けを外部キー列として表します。 |
5 | Navigation JavaとRDBMSでオブジェクトにアクセスする方法は根本的に異なります。 |
ザ・ Object-Relational Mapping(ORM)は、上記のすべてのインピーダンス不整合を処理するためのソリューションです。
ORMとは何ですか?
ORMは Object-Relational Mapping(ORM)は、リレーショナルデータベースとJava、C#などのオブジェクト指向プログラミング言語との間でデータを変換するためのプログラミング手法です。
ORMシステムには、プレーンJDBCに比べて次の利点があります。
シニア番号 | 利点 |
---|---|
1 | DBテーブルではなくオブジェクトにアクセスするビジネスコードを見てみましょう。 |
2 | SQLクエリの詳細をオブジェクト指向ロジックから非表示にします。 |
3 | 「内部のJDBC」に基づいています。 |
4 | データベースの実装に対処する必要はありません。 |
5 | データベース構造ではなく、ビジネスコンセプトに基づくエンティティ。 |
6 | トランザクション管理と自動キー生成。 |
7 | アプリケーションの迅速な開発。 |
ORMソリューションは、次の4つのエンティティで構成されています-
シニア番号 | ソリューション |
---|---|
1 | 永続クラスのオブジェクトに対して基本的なCRUD操作を実行するためのAPI。 |
2 | クラスおよびクラスのプロパティを参照するクエリを指定するための言語またはAPI。 |
3 | マッピングメタデータを指定するための構成可能な機能。 |
4 | トランザクションオブジェクトと対話して、ダーティチェック、レイジーアソシエーションフェッチ、およびその他の最適化機能を実行する手法。 |
JavaORMフレームワーク
Javaにはいくつかの永続的なフレームワークとORMオプションがあります。永続フレームワークは、オブジェクトをリレーショナルデータベースに格納および取得するORMサービスです。
- エンタープライズJavaBeansエンティティBean
- Javaデータオブジェクト
- Castor
- TopLink
- 春のDAO
- Hibernate
- などなど
Hibernateは Object-Relational MJAVA用のapping(ORM)ソリューション。これは、2001年にGavin Kingによって作成されたオープンソースの永続フレームワークです。これは、あらゆるJavaアプリケーション向けの強力で高性能なオブジェクトリレーショナル永続性およびクエリサービスです。
Hibernateは、Javaクラスをデータベーステーブルに、Javaデータ型からSQLデータ型にマップし、開発者を一般的なデータ永続性関連のプログラミングタスクの95%から解放します。
Hibernateは、従来のJavaオブジェクトとデータベースサーバーの間に位置し、適切なO / Rメカニズムとパターンに基づいてこれらのオブジェクトを永続化するためのすべての作業を処理します。
Hibernateの利点
Hibernateは、XMLファイルを使用して、コード行を記述せずにJavaクラスをデータベーステーブルにマッピングします。
データベースとの間で直接Javaオブジェクトを格納および取得するための単純なAPIを提供します。
データベースまたはいずれかのテーブルに変更がある場合は、XMLファイルのプロパティのみを変更する必要があります。
なじみのないSQLタイプを抽象化し、なじみのあるJavaオブジェクトを回避する方法を提供します。
Hibernateは、動作するためにアプリケーションサーバーを必要としません。
データベースのオブジェクトの複雑な関連付けを操作します。
スマートフェッチ戦略により、データベースアクセスを最小限に抑えます。
データの簡単なクエリを提供します。
サポートされているデータベース
Hibernateはほとんどすべての主要なRDBMSをサポートします。以下は、Hibernateでサポートされているデータベースエンジンのいくつかのリストです。
- HSQLデータベースエンジン
- DB2/NT
- MySQL
- PostgreSQL
- FrontBase
- Oracle
- Microsoft SQLServerデータベース
- Sybase SQL Server
- Informix Dynamic Server
サポートされているテクノロジー
Hibernateは、次のような他のさまざまなテクノロジーをサポートしています。
- XDoclet Spring
- J2EE
- Eclipseプラグイン
- Maven
Hibernateは、ユーザーが基盤となるAPIを知らなくても操作できるようにする階層化アーキテクチャを備えています。Hibernateは、データベースと構成データを利用して、アプリケーションに永続性サービス(および永続性オブジェクト)を提供します。
以下は、Hibernateアプリケーションアーキテクチャの非常に高レベルのビューです。
以下は、重要なコアクラスを備えたHibernateアプリケーションアーキテクチャの詳細図です。
Hibernateは、JDBC、Java Transaction API(JTA)、Java Naming and Directory Interface(JNDI)などのさまざまな既存のJavaAPIを使用します。JDBCは、リレーショナルデータベースに共通する機能の初歩的なレベルの抽象化を提供し、JDBCドライバーを備えたほぼすべてのデータベースをHibernateでサポートできるようにします。JNDIとJTAを使用すると、HibernateをJ2EEアプリケーションサーバーと統合できます。
次のセクションでは、Hibernateアプリケーションアーキテクチャに関連する各クラスオブジェクトについて簡単に説明します。
構成オブジェクト
Configurationオブジェクトは、Hibernateアプリケーションで作成する最初のHibernateオブジェクトです。通常、アプリケーションの初期化中に1回だけ作成されます。これは、Hibernateに必要な構成ファイルまたはプロパティファイルを表します。
構成オブジェクトは、2つの主要なコンポーネントを提供します-
Database Connection−これは、Hibernateでサポートされている1つ以上の構成ファイルを介して処理されます。これらのファイルはhibernate.properties そして hibernate.cfg.xml。
Class Mapping Setup −このコンポーネントは、Javaクラスとデータベーステーブル間の接続を作成します。
SessionFactoryオブジェクト
構成オブジェクトは、SessionFactoryオブジェクトを作成するために使用されます。このオブジェクトは、提供された構成ファイルを使用してアプリケーションのHibernateを構成し、Sessionオブジェクトをインスタンス化できるようにします。SessionFactoryはスレッドセーフなオブジェクトであり、アプリケーションのすべてのスレッドによって使用されます。
SessionFactoryは重量級のオブジェクトです。通常、アプリケーションの起動時に作成され、後で使用するために保持されます。別の構成ファイルを使用して、データベースごとに1つのSessionFactoryオブジェクトが必要になります。したがって、複数のデータベースを使用している場合は、複数のSessionFactoryオブジェクトを作成する必要があります。
セッションオブジェクト
セッションは、データベースとの物理的な接続を取得するために使用されます。Sessionオブジェクトは軽量で、データベースとの対話が必要になるたびにインスタンス化されるように設計されています。永続オブジェクトは、Sessionオブジェクトを介して保存および取得されます。
セッションオブジェクトは通常スレッドセーフではないため、長期間開いたままにしないでください。必要に応じて作成および破棄する必要があります。
トランザクションオブジェクト
トランザクションはデータベースとの作業単位を表し、ほとんどのRDBMSはトランザクション機能をサポートしています。Hibernateのトランザクションは、基盤となるトランザクションマネージャーとトランザクション(JDBCまたはJTAから)によって処理されます。
これはオプションのオブジェクトであり、Hibernateアプリケーションはこのインターフェースを使用せず、代わりに独自のアプリケーションコードでトランザクションを管理することを選択できます。
クエリオブジェクト
クエリオブジェクトは、SQLまたはHibernateクエリ言語(HQL)文字列を使用して、データベースからデータを取得し、オブジェクトを作成します。クエリインスタンスは、クエリパラメータをバインドし、クエリによって返される結果の数を制限し、最後にクエリを実行するために使用されます。
基準オブジェクト
基準オブジェクトは、オブジェクト指向の基準クエリを作成および実行してオブジェクトを取得するために使用されます。
この章では、Hibernateおよびその他の関連パッケージをインストールして、Hibernateアプリケーション用の環境を準備する方法について説明します。MySQLデータベースを使用してHibernateの例を実験するので、MySQLデータベースのセットアップがすでに完了していることを確認してください。MySQLの詳細については、MySQLチュートリアルを確認してください。
Hibernateのダウンロード
システムに最新バージョンのJavaがすでにインストールされていることを前提としています。以下は、システムにHibernateをダウンロードしてインストールするための簡単な手順です。
HibernateをWindowsにインストールするかUnixにインストールするかを選択し、次の手順に進んでWindows用の.zipファイルとUnix用の.tzファイルをダウンロードします。
Hibernateの最新バージョンをからダウンロードします http://www.hibernate.org/downloads。
このチュートリアルを書いている時点で、私はダウンロードしました hibernate-distribution3.6.4.Final ダウンロードしたファイルを解凍すると、次の画像に示すようなディレクトリ構造が得られます。
Hibernateのインストール
Hibernateインストールファイルの最新バージョンをダウンロードして解凍したら、次の2つの簡単な手順を実行する必要があります。CLASSPATH変数を適切に設定していることを確認してください。そうしないと、アプリケーションのコンパイル中に問題が発生します。
次に、すべてのライブラリファイルをからコピーします /lib CLASSPATHに追加し、クラスパス変数を変更してすべてのJARを含めます-
最後に、コピー hibernate3.jarCLASSPATHにファイルします。このファイルはインストールのルートディレクトリにあり、Hibernateが作業を行うために必要なプライマリJARです。
Hibernateの前提条件
以下は、Hibernateに必要なパッケージ/ライブラリのリストです。Hibernateを開始する前にそれらをインストールする必要があります。これらのパッケージをインストールするには、ライブラリファイルをからコピーする必要があります/lib CLASSPATHに挿入し、それに応じてCLASSPATH変数を変更します。
シニア番号 | パッケージ/ライブラリ |
---|---|
1 | dom4j XML解析www.dom4j.org/ |
2 | Xalan XSLTプロセッサ https://xml.apache.org/xalan-j/ |
3 | Xerces XercesJavaパーサー https://xml.apache.org/xerces-j/ |
4 | cglib 実行時のJavaクラスへの適切な変更 http://cglib.sourceforge.net/ |
5 | log4j Faremworkのロギング https://logging.apache.org/log4j |
6 | Commons ロギング、Eメールなど。 https://jakarta.apache.org/commons |
7 | SLF4J Javaのロギングファサード https://www.slf4j.org |
Hibernateは、Javaクラスがデータベーステーブルにどのように関連するかを定義するマッピング情報をどこで見つけるかを事前に知る必要があります。Hibernateには、データベースおよびその他の関連パラメーターに関連する一連の構成設定も必要です。このような情報はすべて、通常、次のような標準のJavaプロパティファイルとして提供されます。hibernate.properties、またはという名前のXMLファイルとして hibernate.cfg.xml。
XML形式のファイルを検討します hibernate.cfg.xml私の例で必要なHibernateプロパティを指定します。ほとんどのプロパティはデフォルト値を取り、本当に必要な場合を除いて、プロパティファイルで指定する必要はありません。このファイルは、アプリケーションのクラスパスのルートディレクトリに保存されます。
Hibernateプロパティ
以下は重要なプロパティのリストです。スタンドアロンの状況でデータベースを構成する必要があります-
シニア番号 | プロパティと説明 |
---|---|
1 | hibernate.dialect このプロパティにより、Hibernateは選択されたデータベースに適切なSQLを生成します。 |
2 | hibernate.connection.driver_class JDBCドライバークラス。 |
3 | hibernate.connection.url データベースインスタンスへのJDBCURL。 |
4 | hibernate.connection.username データベースのユーザー名。 |
5 | hibernate.connection.password データベースのパスワード。 |
6 | hibernate.connection.pool_size Hibernateデータベース接続プールで待機している接続の数を制限します。 |
7 | hibernate.connection.autocommit 自動コミットモードをJDBC接続に使用できるようにします。 |
アプリケーションサーバーおよびJNDIとともにデータベースを使用している場合は、次のプロパティを構成する必要があります。
シニア番号 | プロパティと説明 |
---|---|
1 | hibernate.connection.datasource アプリケーションに使用している、アプリケーションサーバーコンテキストで定義されたJNDI名。 |
2 | hibernate.jndi.class JNDIのInitialContextクラス。 |
3 | hibernate.jndi.<JNDIpropertyname> 必要なJNDIプロパティをJNDIInitialContextに渡します。 |
4 | hibernate.jndi.url JNDIのURLを提供します。 |
5 | hibernate.connection.username データベースのユーザー名。 |
6 | hibernate.connection.password データベースのパスワード。 |
MySQLデータベースで休止状態
MySQLは、今日利用可能な最も人気のあるオープンソースデータベースシステムの1つです。作成しましょうhibernate.cfg.xml構成ファイルを作成し、アプリケーションのクラスパスのルートに配置します。あなたはあなたが持っていることを確認する必要がありますtestdb MySQLデータベースで利用可能なデータベースであり、ユーザーがいます test データベースにアクセスできます。
XML構成ファイルは、Hibernate3構成DTDに準拠している必要があります。 http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd。
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name = "hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name = "hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- Assume test is the database name -->
<property name = "hibernate.connection.url">
jdbc:mysql://localhost/test
</property>
<property name = "hibernate.connection.username">
root
</property>
<property name = "hibernate.connection.password">
root123
</property>
<!-- List of XML mapping files -->
<mapping resource = "Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
上記の構成ファイルには、 <mapping> hibernatemappingファイルに関連するタグ。次の章で、hibernateマッピングファイルとは何か、どのように、なぜそれを使用するのかを説明します。
以下は、さまざまな重要なデータベースの方言プロパティタイプのリストです。
シニア番号 | データベースと方言のプロパティ |
---|---|
1 | DB2 org.hibernate.dialect.DB2Dialect |
2 | HSQLDB org.hibernate.dialect.HSQLDialect |
3 | HypersonicSQL org.hibernate.dialect.HSQLDialect |
4 | Informix org.hibernate.dialect.InformixDialect |
5 | Ingres org.hibernate.dialect.IngresDialect |
6 | Interbase org.hibernate.dialect.InterbaseDialect |
7 | Microsoft SQL Server 2000 org.hibernate.dialect.SQLServerDialect |
8 | Microsoft SQL Server 2005 org.hibernate.dialect.SQLServer2005Dialect |
9 | Microsoft SQL Server 2008 org.hibernate.dialect.SQLServer2008Dialect |
10 | MySQL org.hibernate.dialect.MySQLDialect |
11 | Oracle (any version) org.hibernate.dialect.OracleDialect |
12 | Oracle 11g org.hibernate.dialect.Oracle10gDialect |
13 | Oracle 10g org.hibernate.dialect.Oracle10gDialect |
14 | Oracle 9i org.hibernate.dialect.Oracle9iDialect |
15 | PostgreSQL org.hibernate.dialect.PostgreSQLDialect |
16 | Progress org.hibernate.dialect.ProgressDialect |
17 | SAP DB org.hibernate.dialect.SAPDBDialect |
18 | Sybase org.hibernate.dialect.SybaseDialect |
19 | Sybase Anywhere org.hibernate.dialect.SybaseAnywhereDialect |
セッションは、データベースとの物理的な接続を取得するために使用されます。Sessionオブジェクトは軽量で、データベースとの対話が必要になるたびにインスタンス化されるように設計されています。永続オブジェクトは、Sessionオブジェクトを介して保存および取得されます。
セッションオブジェクトは通常スレッドセーフではないため、長期間開いたままにしないでください。必要に応じて作成および破棄する必要があります。セッションの主な機能は、マップされたエンティティクラスのインスタンスの操作を提供、作成、読み取り、および削除することです。
インスタンスは、特定の時点で次の3つの状態のいずれかに存在する可能性があります-
transient −セッションに関連付けられておらず、データベースに表現がなく、識別子値がない永続クラスの新しいインスタンスは、Hibernateによって一時的と見なされます。
persistent−一時インスタンスをセッションに関連付けることで、一時インスタンスを永続化できます。永続インスタンスには、データベース内の表現、識別子値があり、セッションに関連付けられています。
detached − Hibernateセッションを閉じると、永続インスタンスはデタッチされたインスタンスになります。
セッションインスタンスは、その永続クラスがシリアル化可能である場合、シリアル化可能です。一般的なトランザクションでは、次のイディオムを使用する必要があります。
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
// do some work
...
tx.commit();
}
catch (Exception e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
セッションが例外をスローした場合、トランザクションをロールバックし、セッションを破棄する必要があります。
セッションインターフェイスメソッド
によって提供される方法はたくさんあります Sessionインターフェイスですが、このチュートリアルで使用するいくつかの重要なメソッドのみをリストします。関連するメソッドの完全なリストについては、Hibernateのドキュメントを確認できますSession そして SessionFactory。
シニア番号 | セッションの方法と説明 |
---|---|
1 | Transaction beginTransaction() 作業単位を開始し、関連するトランザクションオブジェクトを返します。 |
2 | void cancelQuery() 現在のクエリの実行をキャンセルします。 |
3 | void clear() セッションを完全にクリアします。 |
4 | Connection close() JDBC接続を解放してクリーンアップすることにより、セッションを終了します。 |
5 | Criteria createCriteria(Class persistentClass) 指定されたエンティティクラス、またはエンティティクラスのスーパークラスに対して、新しいCriteriaインスタンスを作成します。 |
6 | Criteria createCriteria(String entityName) 指定されたエンティティ名に対して、新しいCriteriaインスタンスを作成します。 |
7 | Serializable getIdentifier(Object object) このセッションに関連付けられている特定のエンティティの識別子値を返します。 |
8 | Query createFilter(Object collection, String queryString) 指定されたコレクションとフィルター文字列に対してQueryの新しいインスタンスを作成します。 |
9 | Query createQuery(String queryString) 指定されたHQLクエリ文字列に対してQueryの新しいインスタンスを作成します。 |
10 | SQLQuery createSQLQuery(String queryString) 指定されたSQLクエリ文字列に対してSQLQueryの新しいインスタンスを作成します。 |
11 | void delete(Object object) データストアから永続インスタンスを削除します。 |
12 | void delete(String entityName, Object object) データストアから永続インスタンスを削除します。 |
13 | Session get(String entityName, Serializable id) 指定された識別子を持つ指定された名前付きエンティティの永続インスタンスを返します。そのような永続インスタンスがない場合はnullを返します。 |
14 | SessionFactory getSessionFactory() このセッションを作成したセッションファクトリを取得します。 |
15 | void refresh(Object object) 基になるデータベースから、指定されたインスタンスの状態を再読み取りします。 |
16 | Transaction getTransaction() このセッションに関連付けられているトランザクションインスタンスを取得します。 |
17 | boolean isConnected() セッションが現在接続されているかどうかを確認します。 |
18 | boolean isDirty() このセッションには、データベースと同期する必要のある変更が含まれていますか? |
19 | boolean isOpen() セッションがまだ開いているかどうかを確認します。 |
20 | Serializable save(Object object) 指定された一時インスタンスを永続化し、最初に生成された識別子を割り当てます。 |
21 | void saveOrUpdate(Object object) 指定されたインスタンスをsave(Object)またはupdate(Object)します。 |
22 | void update(Object object) 指定されたデタッチされたインスタンスの識別子で永続インスタンスを更新します。 |
23 | void update(String entityName, Object object) 指定されたデタッチされたインスタンスの識別子で永続インスタンスを更新します。 |
Hibernateの全体的な概念は、Javaクラス属性から値を取得し、それらをデータベーステーブルに永続化することです。マッピングドキュメントは、Hibernateがクラスから値を取得し、それらをテーブルおよび関連フィールドにマッピングする方法を決定するのに役立ちます。
オブジェクトまたはインスタンスがデータベーステーブルに格納されるJavaクラスは、Hibernateでは永続クラスと呼ばれます。Hibernateは、これらのクラスがいくつかの単純なルール(別名、Plain Old Java Object (POJO)プログラミングモデル。
永続クラスには次の主要なルールがありますが、これらのルールはどれも厳しい要件ではありません。
永続化されるすべてのJavaクラスには、デフォルトのコンストラクターが必要です。
Hibernateおよびデータベース内のオブジェクトを簡単に識別できるように、すべてのクラスにIDが含まれている必要があります。このプロパティは、データベーステーブルの主キー列にマップされます。
永続化されるすべての属性は、プライベートとして宣言され、 getXXX そして setXXX JavaBeanスタイルで定義されたメソッド。
Hibernateの中心的な機能であるプロキシは、永続クラスが非最終であるか、すべてのパブリックメソッドを宣言するインターフェイスの実装に依存します。
EJBフレームワークに必要ないくつかの特殊なクラスおよびインターフェースを拡張または実装しないすべてのクラス。
POJO名は、特定のオブジェクトが通常のJavaオブジェクトであり、特別なオブジェクトではなく、特にEnterpriseJavaBeanではないことを強調するために使用されます。
簡単なPOJOの例
上記のいくつかのルールに基づいて、POJOクラスを次のように定義できます。
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
public Employee() {}
public Employee(String fname, String lname, int salary) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
}
オブジェクト/リレーショナルマッピングは通常、XMLドキュメントで定義されます。このマッピングファイルはHibernateに指示します—定義されたクラスをデータベーステーブルにマッピングする方法は?
多くのHibernateユーザーはXMLを手動で作成することを選択しますが、マッピングドキュメントを生成するためのツールは多数存在します。これらには以下が含まれますXDoclet, Middlegen そして AndroMDA 上級のHibernateユーザー向け。
オブジェクトが次のセクションで定義されたテーブルに保持される、以前に定義されたPOJOクラスについて考えてみましょう。
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
public Employee() {}
public Employee(String fname, String lname, int salary) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
}
永続性を提供する各オブジェクトに対応する1つのテーブルがあります。上記のオブジェクトを次のRDBMSテーブルに格納および取得する必要があることを考慮してください-
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
上記の2つのエンティティに基づいて、次のマッピングファイルを定義できます。このファイルは、定義された1つまたは複数のクラスをデータベーステーブルにマッピングする方法をHibernateに指示します。
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Employee" table = "EMPLOYEE">
<meta attribute = "class-description">
This class contains the employee detail.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "firstName" column = "first_name" type = "string"/>
<property name = "lastName" column = "last_name" type = "string"/>
<property name = "salary" column = "salary" type = "int"/>
</class>
</hibernate-mapping>
マッピングドキュメントは、<classname> .hbm.xml形式のファイルに保存する必要があります。マッピングドキュメントをファイルEmployee.hbm.xmlに保存しました。
マッピングファイルで使用されるマッピング要素について少し詳しく理解してみましょう-
マッピングドキュメントは、 <hibernate-mapping> すべてのを含むルート要素として <class> 要素。
ザ・ <class>要素は、Javaクラスからデータベーステーブルへの特定のマッピングを定義するために使用されます。Javaクラス名は、name クラス要素とデータベースの属性 table nameは、table属性を使用して指定されます。
ザ・ <meta> elementはオプションの要素であり、クラスの説明を作成するために使用できます。
ザ・ <id>elementは、クラス内の一意のID属性をデータベーステーブルの主キーにマップします。ザ・name id要素の属性は、クラス内のプロパティを参照し、 column属性は、データベーステーブルの列を参照します。ザ・type 属性はHibernateマッピングタイプを保持します。このマッピングタイプはJavaからSQLデータタイプに変換されます。
ザ・ <generator>id要素内の要素は、主キー値を自動的に生成するために使用されます。ザ・class ジェネレータ要素の属性はに設定されます native 休止状態にどちらかをピックアップさせる identity, sequence、または hilo 基盤となるデータベースの機能に応じて主キーを作成するアルゴリズム。
ザ・ <property>elementは、Javaクラスプロパティをデータベーステーブルの列にマップするために使用されます。ザ・name 要素の属性は、クラス内のプロパティを参照し、 column属性は、データベーステーブルの列を参照します。ザ・type 属性はHibernateマッピングタイプを保持します。このマッピングタイプはJavaからSQLデータタイプに変換されます。
マッピングドキュメントで使用される他の属性と要素が利用可能であり、他のHibernate関連のトピックについて説明しながら、できるだけ多くのことをカバーしようと思います。
Hibernateマッピングドキュメントを準備すると、Javaデータ型をRDBMSデータ型にマッピングすることがわかります。ザ・typesマッピングファイルで宣言および使用されるのはJavaデータ型ではありません。SQLデータベースタイプでもありません。これらのタイプはHibernate mapping types、JavaからSQLデータ型に、またはその逆に変換できます。
この章では、すべての基本、日付と時刻、ラージオブジェクト、およびその他のさまざまな組み込みマッピングタイプを一覧表示します。
プリミティブ型
マッピングタイプ | Javaタイプ | ANSISQLタイプ |
---|---|---|
整数 | intまたはjava.lang.Integer | 整数 |
長いです | longまたはjava.lang.Long | BIGINT |
ショート | shortまたはjava.lang.Short | SMALLINT |
浮く | floatまたはjava.lang.Float | 浮く |
ダブル | doubleまたはjava.lang.Double | ダブル |
big_decimal | java.math.BigDecimal | 数値 |
キャラクター | java.lang.String | CHAR(1) |
ストリング | java.lang.String | VARCHAR |
バイト | バイトまたはjava.lang.Byte | TINYINT |
ブール値 | booleanまたはjava.lang.Boolean | ビット |
はい・いいえ | booleanまたはjava.lang.Boolean | CHAR(1)( 'Y'または 'N') |
真/偽 | booleanまたはjava.lang.Boolean | CHAR(1)( 'T'または 'F') |
日付と時刻のタイプ
マッピングタイプ | Javaタイプ | ANSISQLタイプ |
---|---|---|
日付 | java.util.Dateまたはjava.sql.Date | 日付 |
時間 | java.util.Dateまたはjava.sql.Time | 時間 |
タイムスタンプ | java.util.Dateまたはjava.sql.Timestamp | タイムスタンプ |
カレンダー | java.util.Calendar | タイムスタンプ |
calendar_date | java.util.Calendar | 日付 |
バイナリおよびラージオブジェクトタイプ
マッピングタイプ | Javaタイプ | ANSISQLタイプ |
---|---|---|
バイナリ | バイト[] | VARBINARY(またはBLOB) |
テキスト | java.lang.String | CLOB |
シリアル化可能 | java.io.Serializableを実装するJavaクラス | VARBINARY(またはBLOB) |
クロブ | java.sql.Clob | CLOB |
ブロブ | java.sql.Blob | BLOB |
JDK関連のタイプ
マッピングタイプ | Javaタイプ | ANSISQLタイプ |
---|---|---|
クラス | java.lang.Class | VARCHAR |
ロケール | java.util.Locale | VARCHAR |
タイムゾーン | java.util.TimeZone | VARCHAR |
通貨 | java.util.Currency | VARCHAR |
ここで、Hibernateを使用してスタンドアロンアプリケーションでJava永続性を提供する方法を理解するための例を見てみましょう。Hibernateテクノロジーを使用してJavaアプリケーションを作成するためのさまざまな手順を実行します。
POJOクラスを作成する
アプリケーション作成の最初のステップは、データベースに永続化されるアプリケーションに応じて、JavaPOJOクラスを構築することです。私たちのことを考えてみましょうEmployee とのクラス getXXX そして setXXX JavaBeans準拠のクラスにするためのメソッド。
POJO(Plain Old Java Object)は、EJBフレームワークにそれぞれ必要ないくつかの特殊なクラスとインターフェースを拡張または実装しないJavaオブジェクトです。通常のJavaオブジェクトはすべてPOJOです。
Hibernateによって永続化されるクラスを設計するときは、JavaBeans準拠のコードと、次のようなインデックスとして機能する1つの属性を提供することが重要です。 id Employeeクラスの属性。
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
public Employee() {}
public Employee(String fname, String lname, int salary) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
}
データベーステーブルの作成
2番目のステップは、データベースにテーブルを作成することです。各オブジェクトに対応する1つのテーブルがあり、永続性を提供する用意があります。上記のオブジェクトを次のRDBMSテーブルに格納および取得する必要があることを考慮してください-
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
マッピング構成ファイルの作成
このステップは、定義された1つまたは複数のクラスをデータベーステーブルにマップする方法をHibernateに指示するマッピングファイルを作成することです。
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Employee" table = "EMPLOYEE">
<meta attribute = "class-description">
This class contains the employee detail.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "firstName" column = "first_name" type = "string"/>
<property name = "lastName" column = "last_name" type = "string"/>
<property name = "salary" column = "salary" type = "int"/>
</class>
</hibernate-mapping>
マッピングドキュメントは、<classname> .hbm.xml形式のファイルに保存する必要があります。マッピングドキュメントをファイルEmployee.hbm.xmlに保存しました。マッピングドキュメントの詳細を少し見てみましょう-
マッピングドキュメントは、すべての<class>要素を含むルート要素として<hibernate-mapping>を持つXMLドキュメントです。
ザ・ <class>要素は、Javaクラスからデータベーステーブルへの特定のマッピングを定義するために使用されます。Javaクラス名は、name クラス要素の属性とデータベーステーブル名は、 table 属性。
ザ・ <meta> elementはオプションの要素であり、クラスの説明を作成するために使用できます。
ザ・ <id>elementは、クラス内の一意のID属性をデータベーステーブルの主キーにマップします。ザ・name id要素の属性は、クラス内のプロパティを参照し、 column属性は、データベーステーブルの列を参照します。ザ・type 属性はHibernateマッピングタイプを保持します。このマッピングタイプはJavaからSQLデータタイプに変換されます。
ザ・ <generator>id要素内の要素は、主キー値を自動的に生成するために使用されます。ザ・class ジェネレータ要素の属性はに設定されます native 休止状態にどちらかをピックアップさせる identity, sequence または hilo 基盤となるデータベースの機能に応じて主キーを作成するアルゴリズム。
ザ・ <property>elementは、Javaクラスプロパティをデータベーステーブルの列にマップするために使用されます。ザ・name 要素の属性は、クラス内のプロパティを参照し、 column属性は、データベーステーブルの列を参照します。ザ・type 属性はHibernateマッピングタイプを保持します。このマッピングタイプはJavaからSQLデータタイプに変換されます。
マッピングドキュメントで使用される他の属性と要素が利用可能であり、他のHibernate関連のトピックについて説明しながら、できるだけ多くのことをカバーしようと思います。
アプリケーションクラスを作成する
最後に、main()メソッドを使用してアプリケーションクラスを作成し、アプリケーションを実行します。このアプリケーションを使用して、いくつかの従業員のレコードを保存してから、それらのレコードにCRUD操作を適用します。
import java.util.List;
import java.util.Date;
import java.util.Iterator;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ManageEmployee ME = new ManageEmployee();
/* Add few employee records in database */
Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
Integer empID3 = ME.addEmployee("John", "Paul", 10000);
/* List down all the employees */
ME.listEmployees();
/* Update employee's records */
ME.updateEmployee(empID1, 5000);
/* Delete an employee from the database */
ME.deleteEmployee(empID2);
/* List down new list of the employees */
ME.listEmployees();
}
/* Method to CREATE an employee in the database */
public Integer addEmployee(String fname, String lname, int salary){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try {
tx = session.beginTransaction();
Employee employee = new Employee(fname, lname, salary);
employeeID = (Integer) session.save(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employeeID;
}
/* Method to READ all the employees */
public void listEmployees( ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
List employees = session.createQuery("FROM Employee").list();
for (Iterator iterator = employees.iterator(); iterator.hasNext();){
Employee employee = (Employee) iterator.next();
System.out.print("First Name: " + employee.getFirstName());
System.out.print(" Last Name: " + employee.getLastName());
System.out.println(" Salary: " + employee.getSalary());
}
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/* Method to UPDATE salary for an employee */
public void updateEmployee(Integer EmployeeID, int salary ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Employee employee = (Employee)session.get(Employee.class, EmployeeID);
employee.setSalary( salary );
session.update(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/* Method to DELETE an employee from the records */
public void deleteEmployee(Integer EmployeeID){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Employee employee = (Employee)session.get(Employee.class, EmployeeID);
session.delete(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
コンパイルと実行
上記のアプリケーションをコンパイルして実行する手順は次のとおりです。コンパイルと実行に進む前に、PATHとCLASSPATHが適切に設定されていることを確認してください。
構成の章で説明されているように、hibernate.cfg.xml構成ファイルを作成します。
上記のように、Employee.hbm.xmlマッピングファイルを作成します。
上記のようにEmployee.javaソースファイルを作成し、コンパイルします。
上記のようにManageEmployee.javaソースファイルを作成し、コンパイルします。
ManageEmployeeバイナリを実行してプログラムを実行します。
次の結果が得られ、EMPLOYEEテーブルにレコードが作成されます。
$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
First Name: Zara Last Name: Ali Salary: 1000
First Name: Daisy Last Name: Das Salary: 5000
First Name: John Last Name: Paul Salary: 10000
First Name: Zara Last Name: Ali Salary: 5000
First Name: John Last Name: Paul Salary: 10000
EMPLOYEEテーブルを確認すると、次のレコードが含まれているはずです-
mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 29 | Zara | Ali | 5000 |
| 31 | John | Paul | 10000 |
+----+------------+-----------+--------+
2 rows in set (0.00 sec
mysql>
これまで、Hibernateを使用した非常に基本的なO / Rマッピングを見てきましたが、3つの最も重要なマッピングのトピックがあり、詳細に学ぶ必要があります。
これらは-
- コレクションのマッピング、
- エンティティクラス間の関連付けのマッピング、および
- コンポーネントマッピング。
コレクションのマッピング
エンティティまたはクラスに特定の変数の値のコレクションがある場合、Javaで使用可能なコレクションインターフェイスのいずれかを使用してそれらの値をマップできます。Hibernateはのインスタンスを永続化できますjava.util.Map, java.util.Set, java.util.SortedMap, java.util.SortedSet, java.util.List、および任意 array 永続的なエンティティまたは値の。
シニア番号 | コレクションの種類とマッピングの説明 |
---|---|
1 | java.util.Set これは<set>要素でマップされ、java.util.HashSetで初期化されます |
2 | java.util.SortedSet これは<set>要素でマップされ、java.util.TreeSetで初期化されます。ザ・sort 属性は、コンパレータまたは自然順序のいずれかに設定できます。 |
3 | java.util.List これは<list>要素でマップされ、java.util.ArrayListで初期化されます |
4 | java.util.Collection これは<bag>または<ibag>要素でマップされ、java.util.ArrayListで初期化されます |
5 | java.util.Map これは<map>要素でマップされ、java.util.HashMapで初期化されます |
6 | java.util.SortedMap これは<map>要素でマップされ、java.util.TreeMapで初期化されます。ザ・sort 属性は、コンパレータまたは自然順序のいずれかに設定できます。 |
配列は、Javaプリミティブ値タイプの場合は<primitive-array>、その他すべての場合は<array>を使用してHibernateでサポートされます。ただし、ほとんど使用されないため、このチュートリアルでは説明しません。
Hibernateで直接サポートされていないユーザー定義のコレクションインターフェイスをマップする場合は、カスタムコレクションのセマンティクスについてHibernateに通知する必要があります。これは非常に簡単ではなく、使用することをお勧めしません。
アソシエーションマッピング
エンティティクラス間の関連付けとテーブル間の関係のマッピングは、ORMの精神です。以下は、オブジェクト間の関係のカーディナリティを表現できる4つの方法です。アソシエーションマッピングは、単方向でも双方向でもかまいません。
シニア番号 | マッピングの種類と説明 |
---|---|
1 | 多対1 Hibernateを使用した多対1の関係のマッピング |
2 | 1対1 Hibernateを使用した1対1の関係のマッピング |
3 | 1対多 Hibernateを使用した1対多の関係のマッピング |
4 | 多対多 Hibernateを使用した多対多の関係のマッピング |
コンポーネントマッピング
Entityクラスがメンバー変数として別のクラスへの参照を持つ可能性が非常に高くなります。参照されるクラスに独自のライフサイクルがなく、所有するエンティティクラスのライフサイクルに完全に依存している場合、参照されるクラスは、したがって、Component class。
コンポーネントのコレクションのマッピングも、構成にわずかな違いがある通常のコレクションのマッピングと同様の方法で可能です。これらの2つのマッピングについて、例を挙げて詳しく説明します。
シニア番号 | マッピングの種類と説明 |
---|---|
1 | コンポーネントマッピング メンバー変数として別のクラスへの参照を持つクラスのマッピング。 |
これまで、HibernateがデータをPOJOからデータベーステーブルに、またはその逆に変換するためにXMLマッピングファイルをどのように使用するかを見てきました。Hibernateアノテーションは、XMLファイルを使用せずにマッピングを定義するための最新の方法です。XMLマッピングメタデータに加えて、またはXMLマッピングメタデータの代わりに注釈を使用できます。
Hibernate Annotationsは、オブジェクトとリレーショナルテーブルのマッピングにメタデータを提供するための強力な方法です。すべてのメタデータは、コードとともにPOJO Javaファイルにまとめられます。これにより、ユーザーは開発中にテーブル構造とPOJOを同時に理解できます。
アプリケーションを他のEJB3準拠のORMアプリケーションに移植できるようにする場合は、注釈を使用してマッピング情報を表す必要がありますが、それでも柔軟性を高めたい場合は、XMLベースのマッピングを使用する必要があります。
Hibernateアノテーションの環境設定
まず最初に、JDK 5.0を使用していることを確認する必要があります。そうでない場合は、アノテーションのネイティブサポートを利用するために、JDKをJDK5.0にアップグレードする必要があります。
次に、sourceforgeから入手できるHibernate 3.xアノテーション配布パッケージをインストールする必要があります:( Hibernate Annotationをダウンロード)そしてコピーhibernate-annotations.jar, lib/hibernate-comons-annotations.jar そして lib/ejb3-persistence.jar HibernateAnnotationsディストリビューションからCLASSPATHへ。
注釈付きクラスの例
Hibernate Annotationの操作中に前述したように、すべてのメタデータはコードとともにPOJO Javaファイルにまとめられます。これにより、ユーザーは開発中にテーブル構造とPOJOを同時に理解できます。
次のEMPLOYEEテーブルを使用してオブジェクトを格納するとします。
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
以下は、定義されたEMPLOYEEテーブルを使用してオブジェクトをマップするための注釈付きのEmployeeクラスのマッピングです。
import javax.persistence.*;
@Entity
@Table(name = "EMPLOYEE")
public class Employee {
@Id @GeneratedValue
@Column(name = "id")
private int id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "salary")
private int salary;
public Employee() {}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
}
Hibernateは、@ Idアノテーションがフィールド上にあることを検出し、実行時にフィールドを介してオブジェクトのプロパティに直接アクセスする必要があると想定します。getId()メソッドに@Idアノテーションを配置した場合、デフォルトでgetterメソッドとsetterメソッドを介してプロパティにアクセスできるようになります。したがって、他のすべてのアノテーションも、選択した戦略に従って、フィールドまたはゲッターメソッドのいずれかに配置されます。
次のセクションでは、上記のクラスで使用されるアノテーションについて説明します。
@Entityアノテーション
EJB3標準アノテーションはに含まれています javax.persistenceパッケージなので、最初のステップとしてこのパッケージをインポートします。次に、@Entity このクラスをエンティティBeanとしてマークするEmployeeクラスへのアノテーション。したがって、少なくとも保護されたスコープで表示される引数なしのコンストラクターが必要です。
@Tableアノテーション
@Tableアノテーションを使用すると、データベース内のエンティティを永続化するために使用されるテーブルの詳細を指定できます。
@Tableアノテーションは、4つの属性を提供します。これにより、テーブルの名前、カタログ、およびスキーマをオーバーライドし、テーブルの列に一意の制約を適用できます。今のところ、EMPLOYEEというテーブル名だけを使用しています。
@Idおよび@GeneratedValueアノテーション
各エンティティBeanには主キーがあり、クラスに注釈を付けます。 @Id注釈。主キーは、テーブル構造に応じて、単一のフィールドまたは複数のフィールドの組み合わせにすることができます。
デフォルトでは、@ Idアノテーションは、使用する最も適切な主キー生成戦略を自動的に決定しますが、これをオーバーライドするには、 @GeneratedValue 2つのパラメータをとる注釈 strategy そして generatorここでは説明しませんので、デフォルトの鍵生成戦略のみを使用しましょう。使用するジェネレーターの種類をHibernateに決定させることで、異なるデータベース間でコードを移植できるようになります。
@Column Annotation
@Columnアノテーションは、フィールドまたはプロパティがマップされる列の詳細を指定するために使用されます。次の最も一般的に使用される属性で列注釈を使用できます-
name 属性を使用すると、列の名前を明示的に指定できます。
length 属性は、特に文字列値の値をマップするために使用される列のサイズを許可します。
nullable 属性を使用すると、スキーマの生成時に列にNOTNULLのマークを付けることができます。
unique 属性を使用すると、列を一意の値のみを含むものとしてマークできます。
アプリケーションクラスを作成する
最後に、main()メソッドを使用してアプリケーションクラスを作成し、アプリケーションを実行します。このアプリケーションを使用して、いくつかの従業員のレコードを保存してから、それらのレコードにCRUD操作を適用します。
import java.util.List;
import java.util.Date;
import java.util.Iterator;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try {
factory = new AnnotationConfiguration().
configure().
//addPackage("com.xyz") //add package if used.
addAnnotatedClass(Employee.class).
buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ManageEmployee ME = new ManageEmployee();
/* Add few employee records in database */
Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
Integer empID3 = ME.addEmployee("John", "Paul", 10000);
/* List down all the employees */
ME.listEmployees();
/* Update employee's records */
ME.updateEmployee(empID1, 5000);
/* Delete an employee from the database */
ME.deleteEmployee(empID2);
/* List down new list of the employees */
ME.listEmployees();
}
/* Method to CREATE an employee in the database */
public Integer addEmployee(String fname, String lname, int salary){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try {
tx = session.beginTransaction();
Employee employee = new Employee();
employee.setFirstName(fname);
employee.setLastName(lname);
employee.setSalary(salary);
employeeID = (Integer) session.save(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employeeID;
}
/* Method to READ all the employees */
public void listEmployees( ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
List employees = session.createQuery("FROM Employee").list();
for (Iterator iterator = employees.iterator(); iterator.hasNext();){
Employee employee = (Employee) iterator.next();
System.out.print("First Name: " + employee.getFirstName());
System.out.print(" Last Name: " + employee.getLastName());
System.out.println(" Salary: " + employee.getSalary());
}
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/* Method to UPDATE salary for an employee */
public void updateEmployee(Integer EmployeeID, int salary ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Employee employee = (Employee)session.get(Employee.class, EmployeeID);
employee.setSalary( salary );
session.update(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/* Method to DELETE an employee from the records */
public void deleteEmployee(Integer EmployeeID){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Employee employee = (Employee)session.get(Employee.class, EmployeeID);
session.delete(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
データベース構成
では、作成しましょう hibernate.cfg.xml データベース関連のパラメータを定義するための構成ファイル。
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name = "hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name = "hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- Assume students is the database name -->
<property name = "hibernate.connection.url">
jdbc:mysql://localhost/test
</property>
<property name = "hibernate.connection.username">
root
</property>
<property name = "hibernate.connection.password">
cohondob
</property>
</session-factory>
</hibernate-configuration>
コンパイルと実行
上記のアプリケーションをコンパイルして実行する手順は次のとおりです。コンパイルと実行に進む前に、PATHとCLASSPATHが適切に設定されていることを確認してください。
パスからEmployee.hbm.xmlマッピングファイルを削除します。
上記のようにEmployee.javaソースファイルを作成し、コンパイルします。
上記のようにManageEmployee.javaソースファイルを作成し、コンパイルします。
ManageEmployeeバイナリを実行してプログラムを実行します。
次の結果が得られ、EMPLOYEEテーブルにレコードが作成されます。
$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
First Name: Zara Last Name: Ali Salary: 1000
First Name: Daisy Last Name: Das Salary: 5000
First Name: John Last Name: Paul Salary: 10000
First Name: Zara Last Name: Ali Salary: 5000
First Name: John Last Name: Paul Salary: 10000
EMPLOYEEテーブルを確認すると、次のレコードが含まれているはずです-
mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 29 | Zara | Ali | 5000 |
| 31 | John | Paul | 10000 |
+----+------------+-----------+--------+
2 rows in set (0.00 sec
mysql>
Hibernateクエリ言語(HQL)は、SQLに似たオブジェクト指向のクエリ言語ですが、テーブルと列を操作する代わりに、永続オブジェクトとそのプロパティを操作します。HQLクエリはHibernateによって従来のSQLクエリに変換され、SQLクエリはデータベースに対してアクションを実行します。
ネイティブSQLを使用してHibernateでSQLステートメントを直接使用できますが、データベースの移植性の煩わしさを回避し、HibernateのSQL生成およびキャッシュ戦略を利用するために、可能な限りHQLを使用することをお勧めします。
SELECT、FROM、WHEREなどのキーワードでは大文字と小文字は区別されませんが、HQLではテーブル名や列名などのプロパティで大文字と小文字が区別されます。
FROM句
使用します FROM完全な永続オブジェクトをメモリにロードする場合は、句。以下は、FROM句を使用する簡単な構文です。
String hql = "FROM Employee";
Query query = session.createQuery(hql);
List results = query.list();
HQLでクラス名を完全修飾する必要がある場合は、パッケージとクラス名を次のように指定するだけです。
String hql = "FROM com.hibernatebook.criteria.Employee";
Query query = session.createQuery(hql);
List results = query.list();
AS条項
ザ・ AS句は、特に長いクエリがある場合に、HQLクエリのクラスにエイリアスを割り当てるために使用できます。たとえば、前の簡単な例は次のようになります。
String hql = "FROM Employee AS E";
Query query = session.createQuery(hql);
List results = query.list();
ザ・ AS キーワードはオプションであり、次のようにクラス名の直後にエイリアスを指定することもできます。
String hql = "FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();
SELECT句
ザ・ SELECT句は、from句よりも結果セットをより細かく制御できます。オブジェクト全体ではなく、オブジェクトのいくつかのプロパティを取得する場合は、SELECT句を使用します。以下は、SELECT句を使用してEmployeeオブジェクトのfirst_nameフィールドのみを取得する簡単な構文です。
String hql = "SELECT E.firstName FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();
ここで注目すべきは Employee.firstName EMPLOYEEテーブルのフィールドではなく、Employeeオブジェクトのプロパティです。
WHERE句
ストレージから返される特定のオブジェクトを絞り込む場合は、WHERE句を使用します。以下は、WHERE句を使用する簡単な構文です。
String hql = "FROM Employee E WHERE E.id = 10";
Query query = session.createQuery(hql);
List results = query.list();
ORDERBY句
HQLクエリの結果を並べ替えるには、 ORDER BY句。結果は、結果セット内のオブジェクトの任意のプロパティで昇順(ASC)または降順(DESC)のいずれかで並べ替えることができます。以下は、ORDERBY句を使用する簡単な構文です。
String hql = "FROM Employee E WHERE E.id > 10 ORDER BY E.salary DESC";
Query query = session.createQuery(hql);
List results = query.list();
複数のプロパティで並べ替える場合は、次のようにカンマで区切って、orderby句の最後に追加のプロパティを追加するだけです。
String hql = "FROM Employee E WHERE E.id > 10 " +
"ORDER BY E.firstName DESC, E.salary DESC ";
Query query = session.createQuery(hql);
List results = query.list();
GROUPBY句
この句を使用すると、Hibernateはデータベースから情報を取得し、属性の値に基づいて情報をグループ化し、通常、結果を使用して集計値を含めることができます。以下は、GROUPBY句を使用する簡単な構文です。
String hql = "SELECT SUM(E.salary), E.firtName FROM Employee E " +
"GROUP BY E.firstName";
Query query = session.createQuery(hql);
List results = query.list();
名前付きパラメーターの使用
Hibernateは、HQLクエリで名前付きパラメーターをサポートします。これにより、ユーザーからの入力を受け入れるHQLクエリを簡単に作成でき、SQLインジェクション攻撃から防御する必要がなくなります。以下は、名前付きパラメーターを使用する簡単な構文です。
String hql = "FROM Employee E WHERE E.id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("employee_id",10);
List results = query.list();
更新条項
一括更新はHibernate3を使用するHQLの新機能であり、Hibernate3ではHibernate2とは異なる方法で削除が機能します。クエリインターフェイスに、HQL UPDATEまたはDELETEステートメントを実行するためのexecuteUpdate()というメソッドが含まれるようになりました。
ザ・ UPDATE句を使用して、1つ以上のオブジェクトの1つ以上のプロパティを更新できます。以下は、UPDATE句を使用する簡単な構文です。
String hql = "UPDATE Employee set salary = :salary " +
"WHERE id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("salary", 1000);
query.setParameter("employee_id", 10);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);
DELETE句
ザ・ DELETE句を使用して、1つ以上のオブジェクトを削除できます。以下は、DELETE句を使用する簡単な構文です。
String hql = "DELETE FROM Employee " +
"WHERE id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("employee_id", 10);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);
INSERT句
HQLはサポートします INSERT INTOあるオブジェクトから別のオブジェクトにレコードを挿入できる場合にのみ句。以下は、INSERTINTO句を使用する簡単な構文です。
String hql = "INSERT INTO Employee(firstName, lastName, salary)" +
"SELECT firstName, lastName, salary FROM old_employee";
Query query = session.createQuery(hql);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);
集計メソッド
HQLは、SQLと同様に、さまざまな集計メソッドをサポートしています。これらはHQLでもSQLと同じように機能し、使用可能な関数のリストは次のとおりです。
シニア番号 | 機能と説明 |
---|---|
1 | avg(property name) プロパティの値の平均 |
2 | count(property name or *) 結果にプロパティが発生する回数 |
3 | max(property name) プロパティ値の最大値 |
4 | min(property name) プロパティ値の最小値 |
5 | sum(property name) プロパティ値の合計 |
ザ・ distinctキーワードは、行セット内の一意の値のみをカウントします。次のクエリは、一意のカウントのみを返します-
String hql = "SELECT count(distinct E.firstName) FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();
クエリを使用したページ付け
ページネーションのためのクエリインターフェイスには2つの方法があります。
シニア番号 | 方法と説明 |
---|---|
1 | Query setFirstResult(int startPosition) このメソッドは、行0から始まる、結果セットの最初の行を表す整数を取ります。 |
2 | Query setMaxResults(int maxResult) このメソッドは、Hibernateに固定数を取得するように指示します maxResults オブジェクトの。 |
上記の2つの方法を一緒に使用すると、WebまたはSwingアプリケーションでページングコンポーネントを構築できます。以下は、一度に10行をフェッチするように拡張できる例です。
String hql = "FROM Employee";
Query query = session.createQuery(hql);
query.setFirstResult(1);
query.setMaxResults(10);
List results = query.list();
Hibernateは、オブジェクトを操作する別の方法を提供し、RDBMSテーブルで利用可能なデータを提供します。メソッドの1つはCriteriaAPIです。これを使用すると、フィルタリングルールと論理条件を適用できる基準クエリオブジェクトをプログラムで構築できます。
休止状態 Session インターフェイスは提供します createCriteria() メソッドを作成するために使用できます Criteria アプリケーションが条件クエリを実行したときに永続オブジェクトのクラスのインスタンスを返すオブジェクト。
以下は、条件クエリの最も単純な例です。これは、Employeeクラスに対応するすべてのオブジェクトを返すだけです。
Criteria cr = session.createCriteria(Employee.class);
List results = cr.list();
基準による制限
使用できます add() 利用可能な方法 Criteria条件クエリの制限を追加するオブジェクト。以下は、給与が2000に等しいレコードを返す制限を追加する例です。
Criteria cr = session.createCriteria(Employee.class);
cr.add(Restrictions.eq("salary", 2000));
List results = cr.list();
以下は、さまざまなシナリオをカバーするいくつかの例であり、要件に従って使用できます-
Criteria cr = session.createCriteria(Employee.class);
// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));
// To get records having salary less than 2000
cr.add(Restrictions.lt("salary", 2000));
// To get records having fistName starting with zara
cr.add(Restrictions.like("firstName", "zara%"));
// Case sensitive form of the above restriction.
cr.add(Restrictions.ilike("firstName", "zara%"));
// To get records having salary in between 1000 and 2000
cr.add(Restrictions.between("salary", 1000, 2000));
// To check if the given property is null
cr.add(Restrictions.isNull("salary"));
// To check if the given property is not null
cr.add(Restrictions.isNotNull("salary"));
// To check if the given property is empty
cr.add(Restrictions.isEmpty("salary"));
// To check if the given property is not empty
cr.add(Restrictions.isNotEmpty("salary"));
次のように、LogicalExpression制限を使用してANDまたはOR条件を作成できます。
Criteria cr = session.createCriteria(Employee.class);
Criterion salary = Restrictions.gt("salary", 2000);
Criterion name = Restrictions.ilike("firstNname","zara%");
// To get records matching with OR conditions
LogicalExpression orExp = Restrictions.or(salary, name);
cr.add( orExp );
// To get records matching with AND conditions
LogicalExpression andExp = Restrictions.and(salary, name);
cr.add( andExp );
List results = cr.list();
上記のすべての条件は、前のチュートリアルで説明したように、HQLで直接使用できます。
基準を使用したページ付け
ページネーションのCriteriaインターフェースには2つの方法があります。
シニア番号 | 方法と説明 |
---|---|
1 | public Criteria setFirstResult(int firstResult) このメソッドは、行0から始まる、結果セットの最初の行を表す整数を取ります。 |
2 | public Criteria setMaxResults(int maxResults) このメソッドは、Hibernateに固定数を取得するように指示します maxResults オブジェクトの。 |
上記の2つの方法を一緒に使用すると、WebまたはSwingアプリケーションでページングコンポーネントを構築できます。以下は、一度に10行をフェッチするように拡張できる例です。
Criteria cr = session.createCriteria(Employee.class);
cr.setFirstResult(1);
cr.setMaxResults(10);
List results = cr.list();
結果の並べ替え
Criteria APIは、 org.hibernate.criterion.Orderオブジェクトのプロパティの1つに従って、結果セットを昇順または降順で並べ替えるクラス。この例は、Orderクラスを使用して結果セットを並べ替える方法を示しています-
Criteria cr = session.createCriteria(Employee.class);
// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));
// To sort records in descening order
cr.addOrder(Order.desc("salary"));
// To sort records in ascending order
cr.addOrder(Order.asc("salary"));
List results = cr.list();
射影と集計
Criteria APIは、 org.hibernate.criterion.Projectionsクラス。プロパティ値の平均、最大、または最小を取得するために使用できます。Projectionsクラスは、取得するためのいくつかの静的ファクトリメソッドを提供するという点で、Restrictionsクラスに似ています。Projection インスタンス。
以下は、さまざまなシナリオをカバーするいくつかの例であり、要件に従って使用できます-
Criteria cr = session.createCriteria(Employee.class);
// To get total row count.
cr.setProjection(Projections.rowCount());
// To get average of a property.
cr.setProjection(Projections.avg("salary"));
// To get distinct count of a property.
cr.setProjection(Projections.countDistinct("firstName"));
// To get maximum of a property.
cr.setProjection(Projections.max("salary"));
// To get minimum of a property.
cr.setProjection(Projections.min("salary"));
// To get sum of a property.
cr.setProjection(Projections.sum("salary"));
基準クエリの例
次のPOJOクラスを検討してください-
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
public Employee() {}
public Employee(String fname, String lname, int salary) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
}
Employeeオブジェクトを格納するために次のEMPLOYEEテーブルを作成しましょう-
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
以下はマッピングファイルです。
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Employee" table = "EMPLOYEE">
<meta attribute = "class-description">
This class contains the employee detail.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "firstName" column = "first_name" type = "string"/>
<property name = "lastName" column = "last_name" type = "string"/>
<property name = "salary" column = "salary" type = "int"/>
</class>
</hibernate-mapping>
最後に、main()メソッドを使用してアプリケーションクラスを作成し、使用するアプリケーションを実行します。 Criteria クエリ-
import java.util.List;
import java.util.Date;
import java.util.Iterator;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Projections;
import org.hibernate.cfg.Configuration;
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ManageEmployee ME = new ManageEmployee();
/* Add few employee records in database */
Integer empID1 = ME.addEmployee("Zara", "Ali", 2000);
Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
Integer empID3 = ME.addEmployee("John", "Paul", 5000);
Integer empID4 = ME.addEmployee("Mohd", "Yasee", 3000);
/* List down all the employees */
ME.listEmployees();
/* Print Total employee's count */
ME.countEmployee();
/* Print Total salary */
ME.totalSalary();
}
/* Method to CREATE an employee in the database */
public Integer addEmployee(String fname, String lname, int salary){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try {
tx = session.beginTransaction();
Employee employee = new Employee(fname, lname, salary);
employeeID = (Integer) session.save(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employeeID;
}
/* Method to READ all the employees having salary more than 2000 */
public void listEmployees( ) {
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Criteria cr = session.createCriteria(Employee.class);
// Add restriction.
cr.add(Restrictions.gt("salary", 2000));
List employees = cr.list();
for (Iterator iterator = employees.iterator(); iterator.hasNext();){
Employee employee = (Employee) iterator.next();
System.out.print("First Name: " + employee.getFirstName());
System.out.print(" Last Name: " + employee.getLastName());
System.out.println(" Salary: " + employee.getSalary());
}
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/* Method to print total number of records */
public void countEmployee(){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Criteria cr = session.createCriteria(Employee.class);
// To get total row count.
cr.setProjection(Projections.rowCount());
List rowCount = cr.list();
System.out.println("Total Coint: " + rowCount.get(0) );
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/* Method to print sum of salaries */
public void totalSalary(){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Criteria cr = session.createCriteria(Employee.class);
// To get total salary.
cr.setProjection(Projections.sum("salary"));
List totalSalary = cr.list();
System.out.println("Total Salary: " + totalSalary.get(0) );
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
コンパイルと実行
上記のアプリケーションをコンパイルして実行する手順は次のとおりです。コンパイルと実行に進む前に、PATHとCLASSPATHが適切に設定されていることを確認してください。
構成の章で説明されているように、hibernate.cfg.xml構成ファイルを作成します。
上記のように、Employee.hbm.xmlマッピングファイルを作成します。
上記のようにEmployee.javaソースファイルを作成し、コンパイルします。
上記のようにManageEmployee.javaソースファイルを作成し、コンパイルします。
ManageEmployeeバイナリを実行してプログラムを実行します。
次の結果が得られ、EMPLOYEEテーブルにレコードが作成されます。
$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
First Name: Daisy Last Name: Das Salary: 5000
First Name: John Last Name: Paul Salary: 5000
First Name: Mohd Last Name: Yasee Salary: 3000
Total Coint: 4
Total Salary: 15000
EMPLOYEEテーブルを確認すると、次のレコードが含まれているはずです-
mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 14 | Zara | Ali | 2000 |
| 15 | Daisy | Das | 5000 |
| 16 | John | Paul | 5000 |
| 17 | Mohd | Yasee | 3000 |
+----+------------+-----------+--------+
4 rows in set (0.00 sec)
mysql>
OracleのクエリヒントやCONNECTキーワードなどのデータベース固有の機能を利用する場合は、ネイティブSQLを使用してデータベースクエリを表現できます。Hibernate 3.xでは、すべての作成、更新、削除、およびロード操作に対して、ストアドプロシージャを含む手書きのSQLを指定できます。
アプリケーションは、セッションからネイティブSQLクエリを作成します。 createSQLQuery() セッションインターフェイスのメソッド-
public SQLQuery createSQLQuery(String sqlString) throws HibernateException
SQLクエリを含む文字列をcreateSQLQuery()メソッドに渡した後、addEntity()、addJoin()、およびaddScalar()メソッドを使用して、SQL結果を既存のHibernateエンティティ、結合、またはスカラー結果のいずれかに関連付けることができます。それぞれ。
スカラークエリ
最も基本的なSQLクエリは、1つ以上のテーブルからスカラー(値)のリストを取得することです。以下は、スカラー値にネイティブSQLを使用するための構文です。
String sql = "SELECT first_name, salary FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List results = query.list();
エンティティクエリ
上記のクエリはすべてスカラー値を返すことに関するもので、基本的には結果セットから「生の」値を返します。以下は、addEntity()を介してネイティブSQLクエリからエンティティオブジェクト全体を取得するための構文です。
String sql = "SELECT * FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
List results = query.list();
名前付きSQLクエリ
以下は、addEntity()を介して名前付きSQLクエリを使用してネイティブSQLクエリからエンティティオブジェクトを取得するための構文です。
String sql = "SELECT * FROM EMPLOYEE WHERE id = :employee_id";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
query.setParameter("employee_id", 10);
List results = query.list();
ネイティブSQLの例
次のPOJOクラスを検討してください-
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
public Employee() {}
public Employee(String fname, String lname, int salary) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
}
Employeeオブジェクトを格納するために次のEMPLOYEEテーブルを作成しましょう-
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
以下はマッピングファイルになります-
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Employee" table = "EMPLOYEE">
<meta attribute = "class-description">
This class contains the employee detail.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "firstName" column = "first_name" type = "string"/>
<property name = "lastName" column = "last_name" type = "string"/>
<property name = "salary" column = "salary" type = "int"/>
</class>
</hibernate-mapping>
最後に、main()メソッドを使用してアプリケーションクラスを作成し、使用するアプリケーションを実行します。 Native SQL クエリ-
import java.util.*;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.SQLQuery;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.cfg.Configuration;
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ManageEmployee ME = new ManageEmployee();
/* Add few employee records in database */
Integer empID1 = ME.addEmployee("Zara", "Ali", 2000);
Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
Integer empID3 = ME.addEmployee("John", "Paul", 5000);
Integer empID4 = ME.addEmployee("Mohd", "Yasee", 3000);
/* List down employees and their salary using Scalar Query */
ME.listEmployeesScalar();
/* List down complete employees information using Entity Query */
ME.listEmployeesEntity();
}
/* Method to CREATE an employee in the database */
public Integer addEmployee(String fname, String lname, int salary){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try {
tx = session.beginTransaction();
Employee employee = new Employee(fname, lname, salary);
employeeID = (Integer) session.save(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employeeID;
}
/* Method to READ all the employees using Scalar Query */
public void listEmployeesScalar( ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
String sql = "SELECT first_name, salary FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List data = query.list();
for(Object object : data) {
Map row = (Map)object;
System.out.print("First Name: " + row.get("first_name"));
System.out.println(", Salary: " + row.get("salary"));
}
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/* Method to READ all the employees using Entity Query */
public void listEmployeesEntity( ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
String sql = "SELECT * FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
List employees = query.list();
for (Iterator iterator = employees.iterator(); iterator.hasNext();){
Employee employee = (Employee) iterator.next();
System.out.print("First Name: " + employee.getFirstName());
System.out.print(" Last Name: " + employee.getLastName());
System.out.println(" Salary: " + employee.getSalary());
}
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
コンパイルと実行
上記のアプリケーションをコンパイルして実行する手順は次のとおりです。コンパイルと実行に進む前に、PATHとCLASSPATHが適切に設定されていることを確認してください。
構成の章で説明されているように、hibernate.cfg.xml構成ファイルを作成します。
上記のように、Employee.hbm.xmlマッピングファイルを作成します。
上記のようにEmployee.javaソースファイルを作成し、コンパイルします。
上記のようにManageEmployee.javaソースファイルを作成し、コンパイルします。
ManageEmployeeバイナリを実行してプログラムを実行します。
次の結果が得られ、EMPLOYEEテーブルにレコードが作成されます。
$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
First Name: Zara, Salary: 2000
First Name: Daisy, Salary: 5000
First Name: John, Salary: 5000
First Name: Mohd, Salary: 3000
First Name: Zara Last Name: Ali Salary: 2000
First Name: Daisy Last Name: Das Salary: 5000
First Name: John Last Name: Paul Salary: 5000
First Name: Mohd Last Name: Yasee Salary: 3000
EMPLOYEEテーブルを確認すると、次のレコードが含まれているはずです-
mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 26 | Zara | Ali | 2000 |
| 27 | Daisy | Das | 5000 |
| 28 | John | Paul | 5000 |
| 29 | Mohd | Yasee | 3000 |
+----+------------+-----------+--------+
4 rows in set (0.00 sec)
mysql>
キャッシングは、システムのパフォーマンスを向上させるメカニズムです。これは、アプリケーションとデータベースの間にあるバッファメモリです。キャッシュメモリは、データベースヒットの数を可能な限り減らすために、最近使用されたデータ項目を格納します。
キャッシングはHibernateにとっても重要です。以下に説明するように、マルチレベルのキャッシュスキームを利用します。
第1レベルのキャッシュ
第1レベルのキャッシュはセッションキャッシュであり、すべてのリクエストが通過する必要のある必須のキャッシュです。Sessionオブジェクトは、データベースにコミットする前に、オブジェクトを独自の権限で保持します。
オブジェクトに複数の更新を発行する場合、Hibernateは、発行される更新SQLステートメントの数を減らすために、更新の実行を可能な限り遅らせようとします。セッションを閉じると、キャッシュされているすべてのオブジェクトが失われ、データベースで永続化または更新されます。
第2レベルのキャッシュ
第2レベルのキャッシュはオプションのキャッシュであり、第2レベルのキャッシュでオブジェクトを見つけようとする前に、常に第1レベルのキャッシュが参照されます。第2レベルのキャッシュは、クラスごとおよびコレクションごとに構成でき、主にセッション間でオブジェクトをキャッシュします。
サードパーティのキャッシュはすべてHibernateで使用できます。アンorg.hibernate.cache.CacheProvider Hibernateにキャッシュ実装へのハンドルを提供するために実装する必要があるインターフェースが提供されます。
クエリレベルのキャッシュ
Hibernateは、第2レベルのキャッシュと緊密に統合されたクエリ結果セットのキャッシュも実装します。
これはオプションの機能であり、キャッシュされたクエリ結果とテーブルが最後に更新されたときのタイムスタンプを保持する2つの追加の物理キャッシュ領域が必要です。これは、同じパラメーターで頻繁に実行されるクエリにのみ役立ちます。
第2レベルのキャッシュ
Hibernateはデフォルトで第1レベルのキャッシュを使用し、第1レベルのキャッシュを使用するために何もする必要はありません。オプションの第2レベルのキャッシュに直接移動しましょう。すべてのクラスがキャッシュの恩恵を受けるわけではないため、第2レベルのキャッシュを無効にできることが重要です。
Hibernateの第2レベルのキャッシュは2つのステップでセットアップされます。まず、使用する同時実行戦略を決定する必要があります。その後、キャッシュプロバイダーを使用して、キャッシュの有効期限と物理キャッシュ属性を構成します。
並行性戦略
同時実行戦略はメディエーターであり、データのアイテムをキャッシュに格納し、キャッシュから取得する役割を果たします。第2レベルのキャッシュを有効にする場合は、永続クラスとコレクションごとに、使用するキャッシュの同時実行戦略を決定する必要があります。
Transactional −この戦略は、まれに更新される場合に、同時トランザクションで古いデータを防止することが重要なほとんどのデータを読み取るために使用します。
Read-write −まれに更新が発生する場合に、同時トランザクションで古いデータを防止することが重要なデータのほとんどを読み取るために、この戦略を再度使用します。
Nonstrict-read-write−この戦略は、キャッシュとデータベース間の一貫性を保証するものではありません。データがほとんど変更されず、古いデータの可能性がほとんどない場合は、この戦略を使用してください。
Read-only−データに適した同時実行戦略。変更されることはありません。参照データとしてのみ使用してください。
に第2レベルのキャッシュを使用する場合 Employee クラスでは、読み取り/書き込み戦略を使用してEmployeeインスタンスをキャッシュするようにHibernateに指示するために必要なマッピング要素を追加しましょう。
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Employee" table = "EMPLOYEE">
<meta attribute = "class-description">
This class contains the employee detail.
</meta>
<cache usage = "read-write"/>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "firstName" column = "first_name" type = "string"/>
<property name = "lastName" column = "last_name" type = "string"/>
<property name = "salary" column = "salary" type = "int"/>
</class>
</hibernate-mapping>
Usage = "read-write"属性は、定義されたキャッシュに読み取り/書き込み同時実行戦略を使用するようにHibernateに指示します。
キャッシュプロバイダー
同時実行戦略を検討した後の次のステップでは、キャッシュ候補クラスを使用してキャッシュプロバイダーを選択します。Hibernateでは、アプリケーション全体に対して単一のキャッシュプロバイダーを選択する必要があります。
シニア番号 | キャッシュの名前と説明 |
---|---|
1 | EHCache メモリまたはディスクとクラスター化されたキャッシュにキャッシュでき、オプションのHibernateクエリ結果キャッシュをサポートします。 |
2 | OSCache 豊富な有効期限ポリシーとクエリキャッシュのサポートにより、単一のJVMでメモリとディスクへのキャッシュをサポートします。 |
3 | warmCache JGroupsに基づくクラスターキャッシュ。クラスター化された無効化を使用しますが、Hibernateクエリキャッシュをサポートしていません。 |
4 | JBoss Cache 完全にトランザクションで複製されたクラスター化されたキャッシュも、JGroupsマルチキャストライブラリに基づいています。レプリケーションまたは無効化、同期または非同期通信、および楽観的および悲観的ロックをサポートします。Hibernateクエリキャッシュがサポートされています。 |
すべてのキャッシュプロバイダーは、すべての同時実行戦略と互換性があるわけではありません。次の互換性マトリックスは、適切な組み合わせを選択するのに役立ちます。
戦略/プロバイダー | 読み取り専用 | Nonstrictread-write | 読み書き | トランザクション |
---|---|---|---|---|
EHCache | バツ | バツ | バツ | |
OSCache | バツ | バツ | バツ | |
SwarmCache | バツ | バツ | ||
JBoss Cache | バツ | バツ |
hibernate.cfg.xml構成ファイルでキャッシュプロバイダーを指定します。第2レベルのキャッシュプロバイダーとしてEHCacheを選択します-
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name = "hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name = "hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- Assume students is the database name -->
<property name = "hibernate.connection.url">
jdbc:mysql://localhost/test
</property>
<property name = "hibernate.connection.username">
root
</property>
<property name = "hibernate.connection.password">
root123
</property>
<property name = "hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
<!-- List of XML mapping files -->
<mapping resource = "Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
次に、キャッシュ領域のプロパティを指定する必要があります。EHCacheには独自の構成ファイルがあります。ehcache.xml、アプリケーションのCLASSPATHに含まれている必要があります。Employeeクラスのehcache.xmlのキャッシュ構成は次のようになります-
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory = "1000"
eternal = "false"
timeToIdleSeconds = "120"
timeToLiveSeconds = "120"
overflowToDisk = "true"
/>
<cache name = "Employee"
maxElementsInMemory = "500"
eternal = "true"
timeToIdleSeconds = "0"
timeToLiveSeconds = "0"
overflowToDisk = "false"
/>
これで、EmployeeクラスとHibernateに対して第2レベルのキャッシュが有効になり、従業員に移動するとき、または識別子で従業員を読み込むときに、第2レベルのキャッシュにアクセスするようになりました。
すべてのクラスを分析し、各クラスに適切なキャッシュ戦略を選択する必要があります。場合によっては、第2レベルのキャッシュによってアプリケーションのパフォーマンスが低下することがあります。したがって、最初にキャッシュを有効にせずにアプリケーションのベンチマークを行い、後で適切なキャッシュを有効にしてパフォーマンスを確認することをお勧めします。キャッシュによってシステムパフォーマンスが向上しない場合は、どのタイプのキャッシュも有効にしても意味がありません。
クエリレベルのキャッシュ
クエリキャッシュを使用するには、最初にを使用してクエリキャッシュをアクティブ化する必要があります hibernate.cache.use_query_cache="true"構成ファイルのプロパティ。このプロパティをtrueに設定すると、Hibernateがクエリと識別子のセットを保持するために必要なキャッシュをメモリに作成するようになります。
次に、クエリキャッシュを使用するには、QueryクラスのsetCacheable(Boolean)メソッドを使用します。例-
Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
List users = query.list();
SessionFactory.closeSession();
Hibernateは、キャッシュ領域の概念を通じて、非常にきめ細かいキャッシュサポートもサポートします。キャッシュ領域は、名前が付けられたキャッシュの一部です。
Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
query.setCacheRegion("employee");
List users = query.list();
SessionFactory.closeSession();
このコードは、このメソッドを使用して、キャッシュの従業員領域にクエリを格納して検索するようにHibernateに指示します。
Hibernateを使用してデータベースに多数のレコードをアップロードする必要がある状況を考えてみてください。以下は、Hibernateを使用してこれを実現するためのコードスニペットです-
Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Employee employee = new Employee(.....);
session.save(employee);
}
tx.commit();
session.close();
デフォルトでは、Hibernateは永続化されたすべてのオブジェクトをセッションレベルのキャッシュにキャッシュし、最終的にアプリケーションはフォールオーバーします。 OutOfMemoryException50,000行目あたりのどこか。使用している場合は、この問題を解決できますbatch processing Hibernateで。
バッチ処理機能を使用するには、最初に hibernate.jdbc.batch_sizeオブジェクトサイズに応じて、20または50の数値へのバッチサイズとして。これにより、休止状態のコンテナに、すべてのX行がバッチとして挿入されることが通知されます。これをコードに実装するには、次のように少し変更する必要があります-
Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Employee employee = new Employee(.....);
session.save(employee);
if( i % 50 == 0 ) { // Same as the JDBC batch size
//flush a batch of inserts and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
上記のコードはINSERT操作では正常に機能しますが、UPDATE操作を実行する場合は、次のコードを使用して実行できます。
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
ScrollableResults employeeCursor = session.createQuery("FROM EMPLOYEE").scroll();
int count = 0;
while ( employeeCursor.next() ) {
Employee employee = (Employee) employeeCursor.get(0);
employee.updateEmployee();
seession.update(employee);
if ( ++count % 50 == 0 ) {
session.flush();
session.clear();
}
}
tx.commit();
session.close();
バッチ処理の例
構成ファイルを変更して追加しましょう hibernate.jdbc.batch_size プロパティ-
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name = "hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name = "hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- Assume students is the database name -->
<property name = "hibernate.connection.url">
jdbc:mysql://localhost/test
</property>
<property name = "hibernate.connection.username">
root
</property>
<property name = "hibernate.connection.password">
root123
</property>
<property name = "hibernate.jdbc.batch_size">
50
</property>
<!-- List of XML mapping files -->
<mapping resource = "Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
次のPOJO従業員クラスを検討してください-
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
public Employee() {}
public Employee(String fname, String lname, int salary) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
}
次のEMPLOYEEテーブルを作成して、Employeeオブジェクトを格納しましょう-
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
以下は、EMPLOYEEテーブルを使用してEmployeeオブジェクトをマップするためのマッピングファイルです。
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Employee" table = "EMPLOYEE">
<meta attribute = "class-description">
This class contains the employee detail.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "firstName" column = "first_name" type = "string"/>
<property name = "lastName" column = "last_name" type = "string"/>
<property name = "salary" column = "salary" type = "int"/>
</class>
</hibernate-mapping>
最後に、main()メソッドを使用してアプリケーションクラスを作成し、使用するアプリケーションを実行します。 flush() そして clear() Hibernateがこれらのレコードをメモリにキャッシュする代わりにデータベースに書き込み続けるように、Sessionオブジェクトで使用可能なメソッド。
import java.util.*;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ManageEmployee ME = new ManageEmployee();
/* Add employee records in batches */
ME.addEmployees( );
}
/* Method to create employee records in batches */
public void addEmployees( ){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try {
tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
String fname = "First Name " + i;
String lname = "Last Name " + i;
Integer salary = i;
Employee employee = new Employee(fname, lname, salary);
session.save(employee);
if( i % 50 == 0 ) {
session.flush();
session.clear();
}
}
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return ;
}
}
コンパイルと実行
上記のアプリケーションをコンパイルして実行する手順は次のとおりです。コンパイルと実行に進む前に、PATHとCLASSPATHが適切に設定されていることを確認してください。
上記の説明に従って、hibernate.cfg.xml構成ファイルを作成します。
上記のように、Employee.hbm.xmlマッピングファイルを作成します。
上記のようにEmployee.javaソースファイルを作成し、コンパイルします。
上記のようにManageEmployee.javaソースファイルを作成し、コンパイルします。
ManageEmployeeバイナリを実行してプログラムを実行すると、EMPLOYEEテーブルに100000レコードが作成されます。
Hibernateで学習したように、オブジェクトが作成され、永続化されます。オブジェクトが変更されたら、データベースに保存し直す必要があります。このプロセスは、次にオブジェクトが必要になるまで続き、永続ストアからロードされます。
したがって、オブジェクトはそのライフサイクルのさまざまな段階を通過し、 Interceptor Interfaceいくつかの必要なタスクを実行するためにさまざまな段階で呼び出すことができるメソッドを提供します。これらのメソッドは、セッションからアプリケーションへのコールバックであり、アプリケーションが永続オブジェクトのプロパティを保存、更新、削除、またはロードする前に検査および/または操作できるようにします。以下は、Interceptorインターフェース内で使用可能なすべてのメソッドのリストです-
シニア番号 | 方法と説明 |
---|---|
1 | findDirty() このメソッドは、 flush() メソッドはSessionオブジェクトで呼び出されます。 |
2 | instantiate() このメソッドは、永続化されたクラスがインスタンス化されるときに呼び出されます。 |
3 | isUnsaved() このメソッドは、オブジェクトがに渡されるときに呼び出されます。 saveOrUpdate() 方法/ |
4 | onDelete() このメソッドは、オブジェクトが削除される前に呼び出されます。 |
5 | onFlushDirty() このメソッドは、フラッシュ、つまり更新操作中にオブジェクトがダーティ(つまり変更された)であることをHibernateが検出したときに呼び出されます。 |
6 | onLoad() このメソッドは、オブジェクトが初期化される前に呼び出されます。 |
7 | onSave() このメソッドは、オブジェクトが保存される前に呼び出されます。 |
8 | postFlush() このメソッドは、フラッシュが発生し、オブジェクトがメモリ内で更新された後に呼び出されます。 |
9 | preFlush() このメソッドは、フラッシュの前に呼び出されます。 |
Hibernate Interceptorを使用すると、オブジェクトがアプリケーションとデータベースの両方に対してどのように見えるかを完全に制御できます。
インターセプターの使い方は?
インターセプターを構築するには、次のいずれかを実装できます Interceptor クラスを直接または拡張する EmptyInterceptorクラス。以下は、HibernateInterceptor機能を使用するための簡単な手順です。
インターセプターを作成する
この例では、EmptyInterceptorを拡張します。この例では、Interceptorのメソッドが次の場合に自動的に呼び出されます。 Employeeオブジェクトが作成および更新されます。要件に応じて、より多くのメソッドを実装できます。
import java.io.Serializable;
import java.util.Date;
import java.util.Iterator;
import org.hibernate.EmptyInterceptor;
import org.hibernate.Transaction;
import org.hibernate.type.Type;
public class MyInterceptor extends EmptyInterceptor {
private int updates;
private int creates;
private int loads;
public void onDelete(Object entity, Serializable id,
Object[] state, String[] propertyNames, Type[] types) {
// do nothing
}
// This method is called when Employee object gets updated.
public boolean onFlushDirty(Object entity, Serializable id,
Object[] currentState, Object[] previousState, String[] propertyNames,
Type[] types) {
if ( entity instanceof Employee ) {
System.out.println("Update Operation");
return true;
}
return false;
}
public boolean onLoad(Object entity, Serializable id,
Object[] state, String[] propertyNames, Type[] types) {
// do nothing
return true;
}
// This method is called when Employee object gets created.
public boolean onSave(Object entity, Serializable id,
Object[] state, String[] propertyNames, Type[] types) {
if ( entity instanceof Employee ) {
System.out.println("Create Operation");
return true;
}
return false;
}
//called before commit into database
public void preFlush(Iterator iterator) {
System.out.println("preFlush");
}
//called after committed into database
public void postFlush(Iterator iterator) {
System.out.println("postFlush");
}
}
POJOクラスを作成する
ここで、EMPLOYEEテーブルとEmployeeクラスを使用して-で遊んだ最初の例を少し変更してみましょう。
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
public Employee() {}
public Employee(String fname, String lname, int salary) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
}
データベーステーブルの作成
2番目のステップは、データベースにテーブルを作成することです。各オブジェクトに対応する1つのテーブルがあり、永続性を提供する用意があります。上で説明したオブジェクトについて考えてみましょう。次のRDBMSテーブルに格納および取得する必要があります-
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
マッピング構成ファイルの作成
このステップは、Hibernateに指示するマッピングファイルを作成することです—定義されたクラスをデータベーステーブルにマッピングする方法。
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Employee" table = "EMPLOYEE">
<meta attribute = "class-description">
This class contains the employee detail.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "firstName" column = "first_name" type = "string"/>
<property name = "lastName" column = "last_name" type = "string"/>
<property name = "salary" column = "salary" type = "int"/>
</class>
</hibernate-mapping>
アプリケーションクラスを作成する
最後に、main()メソッドを使用してアプリケーションクラスを作成し、アプリケーションを実行します。ここで、セッションオブジェクトを作成するときに、Interceptorクラスを引数として使用したことに注意してください。
import java.util.List;
import java.util.Date;
import java.util.Iterator;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ManageEmployee ME = new ManageEmployee();
/* Add few employee records in database */
Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
Integer empID3 = ME.addEmployee("John", "Paul", 10000);
/* List down all the employees */
ME.listEmployees();
/* Update employee's records */
ME.updateEmployee(empID1, 5000);
/* Delete an employee from the database */
ME.deleteEmployee(empID2);
/* List down new list of the employees */
ME.listEmployees();
}
/* Method to CREATE an employee in the database */
public Integer addEmployee(String fname, String lname, int salary){
Session session = factory.openSession( new MyInterceptor() );
Transaction tx = null;
Integer employeeID = null;
try {
tx = session.beginTransaction();
Employee employee = new Employee(fname, lname, salary);
employeeID = (Integer) session.save(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employeeID;
}
/* Method to READ all the employees */
public void listEmployees( ){
Session session = factory.openSession( new MyInterceptor() );
Transaction tx = null;
try {
tx = session.beginTransaction();
List employees = session.createQuery("FROM Employee").list();
for (Iterator iterator = employees.iterator(); iterator.hasNext();){
Employee employee = (Employee) iterator.next();
System.out.print("First Name: " + employee.getFirstName());
System.out.print(" Last Name: " + employee.getLastName());
System.out.println(" Salary: " + employee.getSalary());
}
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/* Method to UPDATE salary for an employee */
public void updateEmployee(Integer EmployeeID, int salary ){
Session session = factory.openSession( new MyInterceptor() );
Transaction tx = null;
try {
tx = session.beginTransaction();
Employee employee = (Employee)session.get(Employee.class, EmployeeID);
employee.setSalary( salary );
session.update(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/* Method to DELETE an employee from the records */
public void deleteEmployee(Integer EmployeeID){
Session session = factory.openSession( new MyInterceptor() );
Transaction tx = null;
try {
tx = session.beginTransaction();
Employee employee = (Employee)session.get(Employee.class, EmployeeID);
session.delete(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
コンパイルと実行
上記のアプリケーションをコンパイルして実行する手順は次のとおりです。コンパイルと実行に進む前に、PATHとCLASSPATHが適切に設定されていることを確認してください。
構成の章で説明されているように、hibernate.cfg.xml構成ファイルを作成します。
上記のように、Employee.hbm.xmlマッピングファイルを作成します。
上記のようにEmployee.javaソースファイルを作成し、コンパイルします。
上記のようにMyInterceptor.javaソースファイルを作成し、コンパイルします。
上記のようにManageEmployee.javaソースファイルを作成し、コンパイルします。
ManageEmployeeバイナリを実行してプログラムを実行します。
次の結果が得られ、EMPLOYEEテーブルにレコードが作成されます。
$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
Create Operation
preFlush
postFlush
Create Operation
preFlush
postFlush
Create Operation
preFlush
postFlush
First Name: Zara Last Name: Ali Salary: 1000
First Name: Daisy Last Name: Das Salary: 5000
First Name: John Last Name: Paul Salary: 10000
preFlush
postFlush
preFlush
Update Operation
postFlush
preFlush
postFlush
First Name: Zara Last Name: Ali Salary: 5000
First Name: John Last Name: Paul Salary: 10000
preFlush
postFlush
EMPLOYEEテーブルを確認すると、次のレコードが含まれているはずです-
mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 29 | Zara | Ali | 5000 |
| 31 | John | Paul | 10000 |
+----+------------+-----------+--------+
2 rows in set (0.00 sec
mysql>