Hibernateでのストアドプロシージャ
1. 概要
ストアドプロシージャは、コンパイルされたSQLステートメントのセットですresiding in the database.ロジックをカプセル化し、他のプログラムと共有するために使用され、インデックスヒントや特定のキーワードなどのデータベース固有の機能を利用できます。
この記事では、Hibernateを使用してMySQL database内のstored procedureを呼び出す方法を示します。
2. MySQLのストアドプロシージャ
Hibernateからストアドプロシージャを呼び出す方法を説明する前に、作成する必要があります。
この簡単なMySQLの例では、create a stored procedureを使用して、fooテーブルからすべてのレコードを取得します。
ストアドプロシージャを作成するには、CREATE PROCEDUREステートメントを使用します。
DELIMITER //
CREATE PROCEDURE GetAllFoos()
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
BEGIN
SELECT * FROM foo;
END //
DELIMITER;
BEGINステートメントの前に、オプションのステートメントを定義できます。 公式のMySQL documentationリンクをたどると、これらのステートメントの詳細にドリルダウンできます。
CALLステートメントを使用して、プロシージャが目的の方法で動作することを確認できます。
CALL GetAllFoos();
ストアドプロシージャが稼働しているので、Hibernateから呼び出す方法に直接ジャンプしましょう。
3. Hibernateでストアドプロシージャを呼び出す
Hibernate 3からは、ストアドプロシージャを含む生のSQLステートメントを使用してデータベースにクエリを実行できるようになりました。
このセクションでは、Hibernateを使用してGetAllFoos()プロシージャを呼び出す方法を説明する、一見基本的な例について説明します。
3.1. 設定
実行可能なコードの記述を開始する前に、プロジェクトでHibernateを構成する必要があります。
そしてもちろん、Mavenの依存関係、MySQL構成、Hibernate構成、SessionFactoryのインスタンス化など、そのすべてについて、Hibernate articleを確認できます。
3.2. CreateNativeSQLメソッドを使用してストアドプロシージャを呼び出す
Hibernateを使用すると、クエリをnative SQL形式で直接表現できます。 したがって、ネイティブSQLクエリを簡単に作成し、CALLステートメントを使用してgetAllFoos()ストアドプロシージャを呼び出すことができます。
Query query = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class);
List allFoos = query.list();
上記のクエリは、各要素がFoo objectであるリストを返します。
addEntity()メソッドを使用して、ネイティブのSQLクエリからエンティティオブジェクトを取得します。そうしないと、ストアドプロシージャが生以外の値を返すたびにClassCastExceptionがスローされます。
3.3. @NamedNativeQueriesを使用してストアドプロシージャを呼び出す
ストアドプロシージャを呼び出す別の方法は、@NamedNativeQueriesアノテーションを使用することです。
@NamedNativeQueriesは、クエリscoped to the persistence unit:という名前のネイティブSQLの配列を指定するために使用されます
@NamedNativeQueries({
@NamedNativeQuery(
name = "callGetAllFoos",
query = "CALL GetAllFoos()",
resultClass = Foo.class)
})
@Entity
public class Foo implements Serializable {
// Model definition
}
名前付きクエリにはそれぞれ、明らかにname属性、実際のSQL query、およびFooマップエンティティを参照するresultClassがあります。
Query query = session.getNamedQuery("callGetAllFoos");
List allFoos = query.list();
resultClass属性は、前の例のaddEntity()メソッドと同じ役割を果たします。
パフォーマンスと生産性に関しては両者の間に実際の違いはないため、これらのアプローチはどちらも同じ意味で使用できます。
3.4. @NamedStoredProcedureQueryを使用してストアドプロシージャを呼び出す
JPA 2.1とEntityManagerFactoryおよびEntityManagerのHibernate実装を使用している場合。
@NamedStoredProcedureQueryアノテーションを使用して、ストアドプロシージャを宣言できます。
@NamedStoredProcedureQuery(
name="GetAllFoos",
procedureName="GetAllFoos",
resultClasses = { Foo.class }
)
@Entity
public class Foo implements Serializable {
// Model Definition
}
名前付きストアドプロシージャクエリを呼び出すには、EntityManager,をインスタンス化してから、createNamedStoredProcedureQuery()メソッドを呼び出してプロシージャ:を作成する必要があります。
StoredProcedureQuery spQuery =
entityManager.createNamedStoredProcedureQuery("getAllFoos");
StoredProcedureQueryオブジェクトでexecute()メソッドを呼び出すことにより、Fooエンティティのリストを直接取得できます。
4. パラメータ付きのストアドプロシージャ
ほとんどすべてのストアドプロシージャにはパラメータが必要です。 このセクションでは、Hibernateのパラメーターを使用してストアドプロシージャを呼び出す方法を示します。
MySQLにgetFoosByName()ストアドプロシージャを作成しましょう。
このプロシージャは、name属性がfooNameパラメータと一致するFooオブジェクトのリストを返します。
DELIMITER //
CREATE PROCEDURE GetFoosByName(IN fooName VARCHAR(255))
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
BEGIN
SELECT * FROM foo WHERE name = fooName;
END //
DELIMITER;
GetFoosByName()プロシージャを呼び出すために、名前付きパラメータを使用します。
Query query = session.createSQLQuery("CALL GetFoosByName(:fooName)")
.addEntity(Foo.class)
.setParameter("fooName","New Foo");
同様に、名前付きパラメーター:fooNameは、@NamedNativeQueryアノテーションとともに使用できます。
@NamedNativeQuery(
name = "callGetFoosByName",
query = "CALL GetFoosByName(:fooName)",
resultClass = Foo.class
)
名前付きクエリは次のように呼び出されます。
Query query = session.getNamedQuery("callGetFoosByName")
.setParameter("fooName","New Foo");
@NamedStoredProcedureQueryアノテーションを使用する場合、@StoredProcedureParameter annotationを使用してパラメーターを指定できます。
@NamedStoredProcedureQuery(
name="GetFoosByName",
procedureName="GetFoosByName",
resultClasses = { Foo.class },
parameters={
@StoredProcedureParameter(name="fooName", type=String.class, mode=ParameterMode.IN)
}
)
registerStoredProcedureParameter()メソッドを使用して、fooNameパラメーターを使用してストアドプロシージャを呼び出すことができます。
StoredProcedureQuery spQuery = entityManager.
createNamedStoredProcedureQuery("GetFoosByName")
.registerStoredProcedureParameter(
"New Foo",
String.class ,
ParameterMode.IN
);
5. 結論
この記事では、さまざまなアプローチを使用してhow to use Hibernate to call a stored procedure in a MySQL databaseを示しました。
not all RDBMS support stored proceduresについて言及する価値があります。
この記事で提供されている例は、リンクされているGitHub projectで確認できます。