Thursday, May 22, 2008

HIBERNATE - Relational Persistence for Idiomatic Java - 16

HIBERNATE - Relational Persistence for Idiomatic Java
Hibernate Reference Documentation
Hibernateレファレンスドキュメンテーション
3.2.2

Table of Contents(コンテンツテーブル)
Preface(序文)
1. Introduction to Hibernate(Hibernateの紹介)
2. Architecture(アーキテクチャ)
3. Configuration(設定)
4. Persistent Classes(永続クラス)
5. Basic O/R Mapping(基本的なO/Rマッピング)
6. Collection Mapping(コレクションのマッピング)
7. Association Mappings(関連マッピング)
8. Component Mapping(コンポーネントのマッピング)
9. Inheritance Mapping(継承マッピング)
10. Working with objects(オブジェクトを扱う)
11. Transactions And Concurrency(トランザクションと並行性)
12. Interceptors and events(インターセプタとイベント)
13. Batch processing(バッチ処理)
14. HQL: The Hibernate Query Language(HQLHibernateクエリ言語)
15. Criteria Queries(Criteria)クエリ
16. Native SQL(ネイティブSQL)
16.1. Using a SQLQuery(SQLクエリを使う)
16.1.1. Scalar queries(スカラークエリ)
16.1.2. Entity queries(エンティティクエリ)
16.1.3. Handling associations and collections((関連とコレクションの操作)
16.1.4. Returning multiple entities(複数エンティティの取得)
16.1.4.1. Alias and property references(Aliasとプロパティのリファレンス)
16.1.5. Returning non-managed entities(管理されていないエンティティの取得)
16.1.6. Handling inheritance(継承と制御)
16.1.7. Parameters(パラメータ)
16.2. Named SQL queries(名前付SQLクエリ)
16.2.1. Using return-property to explicitly specify column/alias names(列とAlias名を明示的に指定するために return-property を使う)
16.2.2. Using stored procedures for querying(クエリのためストアドプロシージャを使う)
16.2.2.1. Rules/limitations for using stored procedures(ストアドプロシージャを使う上でのルールと制限)
16.3. Custom SQL for create, update and delete(作成、更新、削除のためのカスタムSQL)
16.4. Custom SQL for loading(ロードのためのカスタムSQL)

Chapter 16. Native SQL(ネイティブクエリ)
You may also express queries in the native SQL dialect of your database. This is useful if you want to utilize database specific features such as query hints or the CONNECTkeyword in Oracle. It also provides a clean migration path from a direct SQL/JDBC based application to Hibernate.
データベースのネイティブSQL方言を使ってクエリを表現することもできます。クエリヒントやOracleCONNECTキーワードのように、データベース独自の機能を利用したいときに使えます。SQL/JDBCを直接使用しているアプリケーションからHibernateへの移行も容易にしています。
Hibernate3 allows you to specify handwritten SQL (including stored procedures) for all create, update, delete, and load operations.
Hibernate3では、生成、更新、削除、読み込み処理のようなすべてのSQL(ストアドプロシージャを含む)を手書きできます。
16.1. Using a SQLQuery(SQLクエリの使用)
Execution of native SQL queries is controlled via the SQLQuery interface, which is obtained by calling Session.createSQLQuery(). The following describes how to use this API for querying.
ネイティブなSQLクエリの実行はSQLQueryインターフェイスを通して制御します。SQLQueryインターフェイスはSession.createSQLQuery()を呼び出して取得します。このAPIを使って問い合わせする方法を以下で説明します。
16.1.1. Scalar queries(スカラーのクエリ)
The most basic SQL query is to get a list of scalars (values).
最も基本的なSQLクエリはスカラー(値)のリストを得ることです。
sess.createSQLQuery("SELECT * FROM CATS").list();
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();
These will both return a List of Object arrays (Object[]) with scalar values for each column in the CATS table. Hibernate will use ResultSetMetadata to deduce the actual order and types of the returned scalar values.
これらはどちらも、CATSテーブルの各カラムのスカラー値を含むObject配列(Object[])のリストを返します。返すスカラー値の実際の順番と型を推定するために、HibernateResultSetMetadataを使用します。
To avoid the overhead of using ResultSetMetadata or simply to be more explicit in what is returned one can use addScalar().
ResultSetMetadataを使用するオーバーヘッドを避けるため、もしくは単に何が返されるか明確にするため、addScalar()を使えます。
sess.createSQLQuery("SELECT * FROM CATS")
 .addScalar("ID", Hibernate.LONG)
 .addScalar("NAME", Hibernate.STRING)
 .addScalar("BIRTHDATE", Hibernate.DATE)
This query specified:
このクエリで指定されているものを下記に示します。
?         the SQL query string(SQLクエリ文字列)
?         the columns and types to return(返されるカラムと型)
This will still return Object arrays, but now it will not use ResultSetMetdata but will instead explicitly get the ID, NAME and BIRTHDATE column as respectively a Long, String and a Short from the underlying resultset. This also means that only these three columns will be returned, even though the query is using * and could return more than the three listed columns.
これはまだObject配列を返しますが、ResultSetMetdataを使用しません。ただし、その代わりに基礎にあるリザルトセットからIDNAMEBIRTHDATE カラムをそれぞれLongStringShort として明示的に取得します。これは3つのカラムを返すのみであることも意味します。たとえ、クエリが*を使用し、列挙した3つより多くのカラムを返せます。
It is possible to leave out the type information for all or some of the scalars.
スカラーの型情報を省くこともできます。
sess.createSQLQuery("SELECT * FROM CATS")
 .addScalar("ID", Hibernate.LONG)
 .addScalar("NAME")
 .addScalar("BIRTHDATE")
This is essentially the same query as before, but now ResultSetMetaData is used to decide the type of NAME and BIRTHDATE where as the type of ID is explicitly specified.
これは本質的に前と同じクエリですが、NAME  BIRTHDATE の型を決めるためにResultSetMetaDataを使用します。一方、ID の型は明示的に指定されています。
How the java.sql.Types returned from ResultSetMetaData is mapped to Hibernate types is controlled by the Dialect. If a specific type is not mapped or does not result in the expected type it is possible to customize it via calls to registerHibernateType in the Dialect.
ResultSetMetaData から返される java.sql.Types  Hibernate の型にマッピングすることは、Dialect が制御します。明示された型がマッピングされていないか、結果の型が期待したものと異なる場合、Dialect registerHibernateTypeを呼び出し、カスタマイズできます。
16.1.2. Entity queries(エンティティのクエリ)
The above queries were all about returning scalar values, basically returning the "raw" values from the resultset. The following shows how to get entity objects from a native sql query via addEntity().
ここまでのクエリは、すべてスカラー値を返すものでした。基本的に、リザルトセットから「未加工」の値を返します。以降では、addEntity()により、ネイティブSQLクエリからエンティティオブジェクトを取得する方法を示します。
sess.createSQLQuery("SELECT * FROM CATS").addEntity(Cat.class);
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class);
This query specified:
このクエリで指定されているものを下記に示します。
?         the SQL query string(SQLクエリ文字列)
?         the entity returned by the query(クエリが返すエンティティとSQLテーブルの別名)
Assuming that Cat is mapped as a class with the columns ID, NAME and BIRTHDATE the above queries will both return a List where each element is a Cat entity.
CatID, NAME, BIRTHDATEのカラムを使ってクラスにマッピングされる場合、上記のクエリはどちらも、要素がCatエンティティであるリストを返します。
If the entity is mapped with a many-to-one to another entity it is required to also return this when performing the native query, otherwise a database specific "column not found" error will occur. The additional columns will automatically be returned when using the * notation, but we prefer to be explicit as in the following example for a many-to-one to a Dog:
エンティティを別のエンティティに多対一でマッピングしている場合は、ネイティブクエリを実行する際に、この別のエンティティを返すことも要求します。さもなければ、データベース固有の「column not found(カラムが見つかりません)」エラーが発生します。*表記を使用した際は、追加のカラムが自動的に返されますが、次の例のように、Dogに多対一であることを明示することを私たちは好みます。
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE, DOG_ID FROM CATS").addEntity(Cat.class);
This will allow cat.getDog() to function properly.
これにより cat.getDog() が正しく機能します。
16.1.3. Handling associations and collections(関連とコレクションの操作)
It is possible to eagerly join in the Dog to avoid the possible extra roundtrip for initializing the proxy. This is done via the addJoin() method, which allows you to join in an association or collection.
プロキシを初期化するための余分な処理を避けるため、Dogの中で即時結合できます。これはaddJoin()メソッドにより行います。関連もしくはコレクションに結合できます。
sess.createSQLQuery("SELECT c.ID, NAME, BIRTHDATE, DOG_ID, D_ID, D_NAME FROM CATS c, DOGS d WHERE c.DOG_ID = d.D_ID")
 .addEntity("cat", Cat.class)
 .addJoin("cat.dog");
In this example the returned Cat's will have their dog property fully initialized without any extra roundtrip to the database. Notice that we added a alias name ("cat") to be able to specify the target property path of the join. It is possible to do the same eager joining for collections, e.g. if the Cat had a one-to-many to Dog instead.
この例の中で、返されるCatは、データベースへの余分処理なしで、完全に初期化されたdogプロパティを持ちます。結合対象のプロパティへのパスを指定できるように、別名(「cat」)を追加したことに注意してください。コレクションの即時結合も同じようにできます。たとえば、Catが一対多でDogを持っていた場合、次のようになります。
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE, D_ID, D_NAME, CAT_ID FROM CATS c, DOGS d WHERE c.ID = d.CAT_ID")
 .addEntity("cat", Cat.class)
 .addJoin("cat.dogs");
<p>At this stage we are reaching the limits of what is possible with native queries without starting to enhance the sql queries to make them usable in Hibernate; the problems starts to arise when returning multiple entities of the same type or when the default alias/column names are not enough.</p>
現在のところ、Hibernateで使いやすくするためのSQLクエリの拡張なしに、ネイティブクエリで何かを可能にする限界に来ています。同じ型のエンティティを複数返す際や、デフォルトの別名や列名で十分ではない場合に、問題は起こり始めます。
16.1.4. Returning multiple entities(複数エンティティの取得)
Until now the result set column names are assumed to be the same as the column names specified in the mapping document. This can be problematic for SQL queries which join multiple tables, since the same column names may appear in more than one table.
ここまでは、リザルトセットのカラム名は、マッピングファイルで指定されたカラム名と同じであると仮定していました。複数のテーブルが同じカラム名を持つ場合があるため、複数テーブルを結合するSQLクエリで問題となる場合があります。
Column alias injection is needed in the following query (which most likely will fail):
下記のような(失敗しそうな)クエリでは、カラム別名インジェクション(column alias injection)が必要です。
sess.createSQLQuery("SELECT c.*, m.*  FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
 .addEntity("cat", Cat.class)
 .addEntity("mother", Cat.class)
The intention for this query is to return two Cat instances per row, a cat and its mother. This will fail since there is a conflict of names since they are mapped to the same column names and on some databases the returned column aliases will most likely be on the form "c.ID", "c.NAME", etc. which are not equal to the columns specificed in the mappings ("ID" and "NAME").
このクエリの意図は、1行ごとに2つのCatインスタンス、つまり猫とその母親を返すということです。同じカラム名にマッピングすることにより名前が衝突するため、このクエリは失敗します。ベータベースによっては、返されるカラムの別名が "c.ID""c.NAME" などの形式であり、マッピングで指定されたカラム("ID"  "NAME")と等しくないため、失敗します。
The following form is not vulnerable to column name duplication:
下記の形式は、カラム名が重複しても大丈夫です。
sess.createSQLQuery("SELECT {cat.*}, {mother.*}  FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
 .addEntity("cat", Cat.class)
 .addEntity("mother", Cat.class)
This query specified:
このクエリで指定されているものを下記に示します。
?         the SQL query string, with placeholders for Hibernate to inject column aliases(SQLクエリ文字列(Hibernateがカラムの別名を挿入するためのプレースホルダを含む))
?         the entities returned by the query(クエリによって返されるエンティティ)
The {cat.*} and {mother.*} notation used above is a shorthand for "all properties". Alternatively, you may list the columns explicity, but even in this case we let Hibernate inject the SQL column aliases for each property. The placeholder for a column alias is just the property name qualified by the table alias. In the following example, we retrieve Cats and their mothers from a different table (cat_log) to the one declared in the mapping metadata. Notice that we may even use the property aliases in the where clause if we like.
上記で使用している {cat.*}  {mother.*} という表記は、「すべてのプロパティ」を表す省略形です。代わりに、明示的にカラムを列挙してもよいですが、その場合は、Hibernateに各プロパティに対応するSQLカラムの別名を挿入させるべきでしょう。カラムの別名のためのプレースホルダは、テーブルの別名によって修飾されたプロパティ名です。下記の例では、別のテーブル cat_log からマッピングメタデータで定義されたCat とその母親を復元します。もし好むなら、where節の中でも、プロパティの別名を使えます。
String sql = "SELECT ID as {c.id}, NAME as {c.name}, " + 
         "BIRTHDATE as {c.birthDate}, MOTHER_ID as {c.mother}, {mother.*} " +
         "FROM CAT_LOG c, CAT_LOG m WHERE {c.mother} = c.ID";

List loggedCats = sess.createSQLQuery(sql)
        .addEntity("cat", Cat.class)
        .addEntity("mother", Cat.class).list()
16.1.4.1. Alias and property references(Aliasとプロパティのリファレンス)
For most cases the above alias injection is needed, but for queries relating to more complex mappings like composite properties, inheritance discriminators, collections etc. there are some specific aliases to use to allow Hibernate to inject the proper aliases.
多くの場合、上記のようなAliasインジェクションが必要です。ただし、複合プロパティ、継承識別子、コレクションなどのようなより複雑なマッピングと関連するクエリがなければ、ある特定のAliasを使用することにより、Hibernateは適切なAliasを挿入できます。
The following table shows the different possibilities of using the alias injection. Note: the alias names in the result are examples, each alias will have a unique and probably different name when used.
Aliasインジェクションとして使用できるものを下表に示します。注意:下表のAlias名は一例です。それぞれの別名は一意であり、使用する際にはおそらく異なる名前を持ちます。
Table 16.1. Alias injection names(Aliasインジェクション名)
Description(説明)
Syntax(構文)
Example()
A simple property(単純なプロパティ)
{[aliasname].[propertyname]
A_NAME as {item.name}
A composite property(複合プロパティ)
{[aliasname].[componentname].[propertyname]}
CURRENCY as {item.amount.currency}, VALUE as {item.amount.value}
Discriminator of an entity(エンティティのクラスを識別する値)
{[aliasname].class}
DISC as {item.class}
All properties of an entity(エンティティの全プロパティ)
{[aliasname].*}
{item.*}
A collection key(コレクションのキー)
{[aliasname].key}
ORGID as {coll.key}
The id of an collection(コレクションのID)
{[aliasname].id}
EMPID as {coll.id}
The element of an collection(コレクションの要素)
{[aliasname].element}
XID as {coll.element}
Property of the element in the collection(コレクションの要素のプロパティ)
{[aliasname].element.[propertyname]}
NAME as {coll.element.name}
All properties of the element in the collection(コレクションの要素の全プロパティ)
{[aliasname].element.*}
{coll.element.*}
All properties of the collection(コレクションの全プロパティ)
{[aliasname].*}
{coll.*}
16.1.5. Returning non-managed entities(管理されていないエンティティの取得)
It is possible to apply a ResultTransformer to native sql queries. Allowing it to e.g. return non-managed entities.
ネイティブSQLクエリに ResultTransformer を適用できます。下記のように、例えば、管理されていないエンティティを返します。
sess.createSQLQuery("SELECT NAME, BIRTHDATE FROM CATS")
        .setResultTransformer(Transformers.aliasToBean(CatDTO.class))
This query specified:
このクエリで指定されているものを下記に示します。
?         the SQL query string(SQLクエリの文字列)
?         a result transformer(結果を変換したもの)
The above query will return a list of CatDTO which has been instantiated and injected the values of NAME and BIRTHNAME into its corresponding properties or fields.
上記のクエリは、インスタンス化し、NAME  BIRTHDATE の値を対応するプロパティもしくはフィールドに挿入したCatDTOのリストを返します。
16.1.6. Handling inheritance(継承と制御)
Native sql queries which query for entities that is mapped as part of an inheritance must include all properties for the baseclass and all it subclasses.
継承の一部としてマッピングされたエンティティを問い合わせるネイティブSQLクエリは、ベースのクラスとそのすべてのサブクラスのプロパティすべてを含まなければなりません。
16.1.7. Parameters(パラメータ)
Native sql queries support positional as well as named parameters:
ネイティブSQLクエリは、以下のように、名前付きパラメータ(:name)と同様に位置パラメータをサポートします。
Query query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like ?").addEntity(Cat.class);
List pusList = query.setString(0, "Pus%").list();
     
query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like :name").addEntity(Cat.class);
List pusList = query.setString("name", "Pus%").list();          
16.2. Named SQL queries(名前付SQLクエリ)
Named SQL queries may be defined in the mapping document and called in exactly the same way as a named HQL query. In this case, we do not need to call addEntity().
名前付きSQLクエリはマッピングドキュメントで定義することができ、名前付きHQLクエリと全く同じ方法で呼ぶことができます。この場合、addEntity()を呼び出す必要はないです。
<sql-query name="persons">
    <return alias="person" class="eg.Person"/>
    SELECT person.NAME AS {person.name},
           person.AGE AS {person.age},
           person.SEX AS {person.sex}
    FROM PERSON person
    WHERE person.NAME LIKE :namePattern
</sql-query>
List people = sess.getNamedQuery("persons")
    .setString("namePattern", namePattern)
    .setMaxResults(50)
    .list();
The <return-join> and <load-collection> elements are used to join associations and define queries which initialize collections, respectively.
関連を結合するためとコレクションを初期化するクエリを定義するために、それぞれ<return-join><load-collection>要素を使います。
<sql-query name="personsWith">
    <return alias="person" class="eg.Person"/>
    <return-join alias="address" property="person.mailingAddress"/>
    SELECT person.NAME AS {person.name},
           person.AGE AS {person.age},
           person.SEX AS {person.sex},
           adddress.STREET AS {address.street},
           adddress.CITY AS {address.city},
           adddress.STATE AS {address.state},
           adddress.ZIP AS {address.zip}
    FROM PERSON person
    JOIN ADDRESS adddress
        ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
    WHERE person.NAME LIKE :namePattern
</sql-query>
A named SQL query may return a scalar value. You must declare the column alias and Hibernate type using the <return-scalar> element:
名前付きSQLクエリはスカラー値を返すこともできます。<return-scalar>要素を使って、列の別名とHibernateの型を宣言しなければなりません。
<sql-query name="mySqlQuery">
    <return-scalar column="name" type="string"/>
    <return-scalar column="age" type="long"/>
    SELECT p.NAME AS name,
           p.AGE AS age,
    FROM PERSON p WHERE p.NAME LIKE 'Hiber%'
</sql-query>
You can externalize the resultset mapping informations in a <resultset> element to either reuse them accross several named queries or through the setResultSetMapping()API.
リザルトセットのマッピング情報を<resultset>に外出しすることができます。複数の名前付きクエリで再利用したり、setResultSetMapping()APIを通して再利用したりできます。
<resultset name="personAddress">
    <return alias="person" class="eg.Person"/>
    <return-join alias="address" property="person.mailingAddress"/>
</resultset>

<sql-query name="personsWith" resultset-ref="personAddress">
    SELECT person.NAME AS {person.name},
           person.AGE AS {person.age},
           person.SEX AS {person.sex},
           adddress.STREET AS {address.street},
           adddress.CITY AS {address.city},
           adddress.STATE AS {address.state},
           adddress.ZIP AS {address.zip}
    FROM PERSON person
    JOIN ADDRESS adddress
        ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
    WHERE person.NAME LIKE :namePattern
</sql-query>
You can alternatively use the resultset mapping information in your hbm files directly in java code.
代わりに、hbmファイル内のリザルトセットのマッピング情報を直接Javaコードの中で使用できます。
List cats = sess.createSQLQuery(
        "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
    )
    .setResultSetMapping("catAndKitten")
    .list();
16.2.1. Using return-property to explicitly specify column/alias names(列とAlias名を明示的に指定するために return-property を使う)
With <return-property> you can explicitly tell Hibernate what column aliases to use, instead of using the {}-syntax to let Hibernate inject its own aliases.
Aliasを挿入するために{}構文を使う代わりに、<return-property>を使い、どの列の別名を使うのかを明示できます。
<sql-query name="mySqlQuery">
    <return alias="person" class="eg.Person">
        <return-property name="name" column="myName"/>
        <return-property name="age" column="myAge"/>
        <return-property name="sex" column="mySex"/>
    </return>
    SELECT person.NAME AS myName,
           person.AGE AS myAge,
           person.SEX AS mySex,
    FROM PERSON person WHERE person.NAME LIKE :name
</sql-query>
<return-property> also works with multiple columns. This solves a limitation with the {}-syntax which can not allow fine grained control of multi-column properties.
<return-property>は複数の列も扱えます。これは、複数列のプロパティをきめ細かく制御できないという、{}構文の制限を解決します。
<sql-query name="organizationCurrentEmployments">
    <return alias="emp" class="Employment">
        <return-property name="salary">
            <return-column name="VALUE"/>
            <return-column name="CURRENCY"/>
        </return-property>
        <return-property name="endDate" column="myEndDate"/>
    </return>
        SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer},
        STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
        REGIONCODE as {emp.regionCode}, EID AS {emp.id}, VALUE, CURRENCY
        FROM EMPLOYMENT
        WHERE EMPLOYER = :id AND ENDDATE IS NULL
        ORDER BY STARTDATE ASC
</sql-query>
Notice that in this example we used <return-property> in combination with the {}-syntax for injection. Allowing users to choose how they want to refer column and properties.
この例では、挿入のための{}構文といっしょに、<return-property>を使っていることに注意してください。列とプロパティをどのように参照するかを選べます。
If your mapping has a discriminator you must use <return-discriminator> to specify the discriminator column.
マッピングに discriminator が含まれている場合、discriminator の列を指定するために、<return-discriminator>を使わなければなりません。
16.2.2. Using stored procedures for querying(クエリのためストアドプロシージャを使う)
Hibernate 3 introduces support for queries via stored procedures and functions. Most of the following documentation is equivalent for both. The stored procedure/function must return a resultset as the first out-parameter to be able to work with Hibernate. An example of such a stored function in Oracle 9 and higher is as follows:
Hibernateはバージョン3から、ストアドプロシージャとストアド関数経由の問い合わせがサポートされました。以降の文書の多くは、両方に当てはまります。ストアドプロシージャやストアド関数をHibernateで使うためには、1番目の出力パラメータとしてリザルトセットを返さなければなりません。Oracle 9(もしくはそれ以上のバージョン)のストアドプロシージャの例を以下に示します。
CREATE OR REPLACE FUNCTION selectAllEmployments
    RETURN SYS_REFCURSOR
AS
    st_cursor SYS_REFCURSOR;
BEGIN
    OPEN st_cursor FOR
 SELECT EMPLOYEE, EMPLOYER,
 STARTDATE, ENDDATE,
 REGIONCODE, EID, VALUE, CURRENCY
 FROM EMPLOYMENT;
      RETURN  st_cursor;
 END;
To use this query in Hibernate you need to map it via a named query.
Hibernateでこのクエリを使うためには、名前付きクエリでマッピングする必要があります。
<sql-query name="selectAllEmployees_SP" callable="true">
    <return alias="emp" class="Employment">
        <return-property name="employee" column="EMPLOYEE"/>
        <return-property name="employer" column="EMPLOYER"/>
        <return-property name="startDate" column="STARTDATE"/>
        <return-property name="endDate" column="ENDDATE"/>
        <return-property name="regionCode" column="REGIONCODE"/>
        <return-property name="id" column="EID"/>
        <return-property name="salary">
            <return-column name="VALUE"/>
            <return-column name="CURRENCY"/>
        </return-property>
    </return>
    { ? = call selectAllEmployments() }
</sql-query>
Notice stored procedures currently only return scalars and entities. <return-join> and<load-collection> are not supported.
注意:今のところ、ストアドプロシージャはスカラーとエンティティを返すのみです。<return-join><load-collection> はサポートされていません。
16.2.2.1. Rules/limitations for using stored procedures(ストアドプロシージャを使う上でのルールと制限)
To use stored procedures with Hibernate the procedures/functions have to follow some rules. If they do not follow those rules they are not usable with Hibernate. If you still want to use these procedures you have to execute them via session.connection(). The rules are different for each database, since database vendors have different stored procedure semantics/syntax.
Hibernateでストアドプロシージャや関数を使うためには、そのプロシージャはいくつかのルールに準拠する必要があります。ルールに準拠していないプロシージャは、Hibernateで使うことはできません。それでも、準拠していないプロシージャを使いたいのであれば、session.connection()を通じて実行しなければなりません。ルールはデータベースごとに異なります。ストアドプロシージャのセマンティックスとシンタックスは、データベースベンダごとに異なるためです。
Stored procedure queries can't be paged with setFirstResult()/setMaxResults().
setFirstResult()/setMaxResults()を使って、ストアドプロシージャクエリをページ分けすることはできません。
Recommended call form is standard SQL92: { ? = call functionName(<parameters>) } or { ? = call procedureName(<parameters>}. Native call syntax is not supported.
推奨する呼び出し方は、標準であるSQL92に従うことです。{ ? = call functionName(<parameters>) }{ ? = call procedureName(<parameters>) }です。ネイティブな呼び出し構文はサポートされていません。
For Oracle the following rules apply:
Oracleには下記のルールが適用されます。
?         A function must return a result set. The first parameter of a procedure must be an OUT that returns a result set. This is done by using a SYS_REFCURSOR type in Oracle 9 or 10. In Oracle you need to define a REF CURSOR type, see Oracle literature.
関数はリザルトセットを返さなければなりません。プロシージャの第一引数はリザルトセットを返すため、OUTでなければなりません。Oracle 910では、SYS_REFCURSORを使うことによってできます。OracleではREF CURSOR型を定義する必要があります。Oracleの文献を参照してください。
For Sybase or MS SQL server the following rules apply:
SybaseMS SQLサーバーに適用されるルールを下記に示します。
?         The procedure must return a result set. Note that since these servers can/will return multiple result sets and update counts, Hibernate will iterate the results and take the first result that is a result set as its return value. Everything else will be discarded.
プロシージャはリザルトセットを返さなければなりません。サーバーは複数のリザルトセットと更新カウントを返しますが、Hibernate1つ目のリザルトセットだけを返すことに注意してください。その他はすべて捨てられます。
?         If you can enable SET NOCOUNT ON in your procedure it will probably be more efficient, but this is not a requirement.
プロシージャの中でSET NOCOUNT ONを有効にできれば、おそらく効率がよくなるでしょう。しかし、これは必要条件ではありません。
16.3. Custom SQL for create, update and delete(作成、更新、削除のためのカスタムSQL)
Hibernate3 can use custom SQL statements for create, update, and delete operations. The class and collection persisters in Hibernate already contain a set of configuration time generated strings (insertsql, deletesql, updatesql etc.). The mapping tags <sql-insert><sql-delete>, and <sql-update> override these strings:
Hibernate3は作成、更新、削除処理のためのカスタムSQL文を使用できます。クラスとコレクションの永続化機構は、コンフィグレーション時に生成された文字列(insertsqldeletesqlupdatesqlなど)のセットをすでに保持しています。これらの文字列より、<sql-insert><sql-delete><sql-update>というマッピングタグが優先されます。
<class name="Person">
    <id name="id">
        <generator class="increment"/>
    </id>
    <property name="name" not-null="true"/>
    <sql-insert>INSERT INTO PERSON (NAME, ID) VALUES ( UPPER(?), ? )</sql-insert>
    <sql-update>UPDATE PERSON SET NAME=UPPER(?) WHERE ID=?</sql-update>
    <sql-delete>DELETE FROM PERSON WHERE ID=?</sql-delete>
</class>
The SQL is directly executed in your database, so you are free to use any dialect you like. This will of course reduce the portability of your mapping if you use database specific SQL.
SQLを直接データベースで実行するため、好みの方言を自由に使用できます。データベース独自のSQLを使えば、当然マッピングのポータビリティが下がります。
Stored procedures are supported if the callable attribute is set:
callable属性をセットすれば、ストアドプロシージャを使用できます。
<class name="Person">
    <id name="id">
        <generator class="increment"/>
    </id>
    <property name="name" not-null="true"/>
    <sql-insert callable="true">{call createPerson (?, ?)}</sql-insert>
    <sql-delete callable="true">{? = call deletePerson (?)}</sql-delete>
    <sql-update callable="true">{? = call updatePerson (?, ?)}</sql-update>
</class>
The order of the positional parameters are currently vital, as they must be in the same sequence as Hibernate expects them.
今のところ、位置パラメータの順番はとても重要です。すなわち、Hibernateが期待する順序でなければなりません。
You can see the expected order by enabling debug logging for theorg.hibernate.persister.entity level. With this level enabled Hibernate will print out the static SQL that is used to create, update, delete etc. entities. (To see the expected sequence, remember to not include your custom SQL in the mapping files as that will override the Hibernate generated static sql.)
org.hiberante.persister.entityレベルのデバッグログを有効にすることによって、期待される順番を確かめられます。このレベルを有効にすることにより、エンティティの作成、更新、削除などで使用される静的なSQLが出力されます。(期待される順序を確認するためには、Hibernateが生成する静的なSQLをオーバーライドするカスタムSQLをマッピングファイルに含めないことを忘れないでください。)
The stored procedures are in most cases (read: better do it than not) required to return the number of rows inserted/updated/deleted, as Hibernate has some runtime checks for the success of the statement. Hibernate always registers the first statement parameter as a numeric output parameter for the CUD operations:
ストアドプロシージャは挿入/更新/削除された行数を返す必要があります(読み込みの場合は、返さないよりは返す方がよいです)。実行時にHibernateSQL文の成功をチェックするからです。Hibernateは、CUD処理のための数値の出力パラメータとして、SQL文の最初のパラメータをいつも記録します。
CREATE OR REPLACE FUNCTION updatePerson (uid IN NUMBER, uname IN VARCHAR2)
    RETURN NUMBER IS
BEGIN

    update PERSON
    set
        NAME = uname,
    where
        ID = uid;

    return SQL%ROWCOUNT;

END updatePerson;
16.4. Custom SQL for loading(ロードのためのカスタムSQL)
You may also declare your own SQL (or HQL) queries for entity loading:
エンティティを読み込むための独自のSQL(もしくはHQL)クエリも宣言できます。
<sql-query name="person">
    <return alias="pers" class="Person" lock-mode="upgrade"/>
    SELECT NAME AS {pers.name}, ID AS {pers.id}
    FROM PERSON
    WHERE ID=?
    FOR UPDATE
</sql-query>
This is just a named query declaration, as discussed earlier. You may reference this named query in a class mapping:
これは、まさに(以前議論した)名前付きクエリの宣言です。この名前付きクエリをクラスのマッピングから参照できます。
<class name="Person">
    <id name="id">
        <generator class="increment"/>
    </id>
    <property name="name" not-null="true"/>
    <loader query-ref="person"/>
</class>
This even works with stored procedures.
これはストアドプロシージャでさえも動作します。
You may even define a query for collection loading:
次のように、コレクションをロードするためのクエリさえ定義してよいです。
<set name="employments" inverse="true">
    <key/>
    <one-to-many class="Employment"/>
    <loader query-ref="employments"/>
</set>
<sql-query name="employments">
    <load-collection alias="emp" role="Person.employments"/>
    SELECT {emp.*}
    FROM EMPLOYMENT emp
    WHERE EMPLOYER = :id
    ORDER BY STARTDATE ASC, EMPLOYEE ASC
</sql-query>
You could even define an entity loader that loads a collection by join fetching:
次のように、結合フェッチによりコレクションをロードするエンティティローダーを定義できます。
<sql-query name="person">
    <return alias="pers" class="Person"/>
    <return-join alias="emp" property="pers.employments"/>
    SELECT NAME AS {pers.*}, {emp.*}
    FROM PERSON pers
    LEFT OUTER JOIN EMPLOYMENT emp
        ON pers.ID = emp.PERSON_ID
    WHERE ID=?
</sql-query>

No comments:

Post a Comment