1. 概要

ストアドプロシージャは、データベースに存在するコンパイル済みSQLステートメントのセットですロジックをカプセル化して他のプログラムと共有するために使用され、インデックスヒントや特定のキーワードなどのデータベース固有の機能を利用できます。

この記事では、 Hibernate を使用して、MySQLデータベースストアドプロシージャを呼び出す方法について説明します。

2. MySQLのストアドプロシージャ

Hibernateからストアドプロシージャを呼び出す方法について説明する前に、それを作成する必要があります。

この簡単なMySQLの例では、ストアドプロシージャを作成して、fooテーブルからすべてのレコードを取得します。

ストアドプロシージャを作成するには、 CREATEPROCEDUREステートメントを使用します。

DELIMITER //
    CREATE PROCEDURE GetAllFoos()
        LANGUAGE SQL
        DETERMINISTIC
        SQL SECURITY DEFINER
        BEGIN
            SELECT * FROM foo;
        END //
DELIMITER;

BEGIN ステートメントの前に、オプションのステートメントを定義できます。 公式のMySQLドキュメントリンクをたどると、これらのステートメントの詳細にドリルダウンできます。

CALL ステートメントを使用して、プロシージャが目的の方法で動作することを確認できます。

CALL GetAllFoos();

ストアドプロシージャが起動して実行されたので、Hibernateからそれを呼び出す方法に直接ジャンプしましょう。

3. Hibernateでストアドプロシージャを呼び出す

Hibernate 3以降、ストアドプロシージャを含む生のSQLステートメントを使用してデータベースにクエリを実行することができます。

このセクションでは、Hibernateを使用して GetAllFoos()プロシージャを呼び出す方法を説明する一見基本的な例を見ていきます。

3.1. 構成

実行可能なコードの記述を開始する前に、プロジェクトでHibernateを構成しておく必要があります。

そしてもちろん、Mavenの依存関係、MySQL構成、Hibernate構成、 SessionFactory のインスタンス化など、すべてについては、Hibernateの記事を確認できます。

3.2. CreateNativeSQLメソッドを使用してストアドプロシージャを呼び出す

Hibernateを使用すると、クエリをネイティブSQL形式で直接表現できます。 したがって、ネイティブSQLクエリを簡単に作成し、 CALLステートメントを使用してgetAllFoos()ストアドプロシージャを呼び出すことができます。

Query query = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class);
List<Foo> allFoos = query.list();

上記のクエリは、各要素が Foo objectであるリストを返します。

addEntity()メソッドを使用して、ネイティブ SQL クエリからエンティティオブジェクトを取得します。そうしないと、ストアドプロシージャが非生の値。

3.3. @NamedNativeQueriesを使用してストアドプロシージャを呼び出す

ストアドプロシージャを呼び出す別の方法は、@NamedNativeQueriesアノテーションを使用することです。

@NamedNativeQueries は、永続性ユニットにスコープされたネイティブ SQL 名前付きクエリの配列を指定するために使用されます:

@NamedNativeQueries({ 
  @NamedNativeQuery(
    name = "callGetAllFoos", 
    query = "CALL GetAllFoos()", 
    resultClass = Foo.class) 
})
@Entity
public class Foo implements Serializable {
    // Model definition
}

名前付きクエリにはそれぞれ、明らかに name 属性、実際の SQLクエリ、およびFooマップエンティティを参照するresultClassがあります。

Query query = session.getNamedQuery("callGetAllFoos");
List<Foo> allFoos = query.list();

resultClass 属性は、前の例の addEntity()メソッドと同じ役割を果たします。

パフォーマンスや生産性に関しては、2つのアプローチの間に実際の違いはないため、これらのアプローチはどちらも同じように使用できます。

3.4. @NamedStoredProcedureQueryを使用してストアドプロシージャを呼び出す

JPA2.1および[X43X]EntityManagerFactoryおよびEntityManagerHibernate実装を使用している場合。

@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のパラメーターを使用してストアドプロシージャを呼び出す方法を示します。

getFoosByName()ストアドプロシージャをMySQLに作成しましょう。

このプロシージャは、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アノテーションを使用してパラメーターを指定できます。

@NamedStoredProcedureQuery(
  name="GetFoosByName",
  procedureName="GetFoosByName",
  resultClasses = { Foo.class },
  parameters={
    @StoredProcedureParameter(name="fooName", type=String.class, mode=ParameterMode.IN)
  }
)

setParameter()メソッドを使用して、fooNameパラメーターを使用してストアドプロシージャを呼び出すことができます。

StoredProcedureQuery spQuery = entityManager.createNamedStoredProcedureQuery("GetFoosByName")
  .setParameter("fooName", "NewFooName");

5. 結論

この記事では、 Hibernateを使用して、さまざまなアプローチを使用してMySQLデータベースのストアドプロシージャを呼び出す方法を示しました。

すべてのRDBMSがストアドプロシージャをサポートしているわけではないことは言及する価値があります。

この記事で提供されている例は、リンクされているGitHubプロジェクトで確認できます。