第13章 ネイティブSQLクエリ

データベースのネイティブSQL方言を使ってクエリを表現することもできます。OracleにおけるCONNECTキーワードのように、そのデータベースに特有の機能を利用するときに有用です。これにより直接のSQL/JDBCベースのアプリケーションからHibernateへのクリーンな移行が可能になります。

13.1. QueryベースSQLの作成

SQLクエリは、普通のHQLクエリと同じQueryインターフェイスを通して公開されています。 唯一の違いはSession.createSQLQuery()を使うことです。

Query sqlQuery = sess.createSQLQuery("select {cat.*} from cats {cat}", "cat", Cat.class);
sqlQuery.setMaxResults(50);
List cats = sqlQuery.list();

以下の3つのパラメータがcreateSQLQuery()に提供されます。:

  • SQLクエリ文字列

  • テーブルの別名

  • クエリにより返される永続クラス

別名はマッピングするクラスのプロパティを参照するSQL文字列の内部で使用されます(このケースではCat)。別名のString配列と対応するクラスのClass配列を与えることで、ひとつの行に つき複数のオブジェクトを取得できます。

13.2. 別名とプロパティ参照

上で使われている{cat.*}は「すべてのプロパティ」を意味する短絡表記です。明示的にプロパティを連ねることもできますが、それにはプロパティそれぞれにSQLカラムの別名を与えるようにしなければなりません。これらのカラムの別名のプレースホルダはテーブルの別名で修飾されるプロパティ名です。以下の例では、異なったテーブル(cat_log)からマッピング・メタデータで定義されたクラスへCatを復元します。where句の中でもプロパティの別名を使用できることに注意してください。

String sql = "select cat.originalId as {cat.id}, "
    + "  cat.mateid as {cat.mate}, cat.sex as {cat.sex}, "
    + "  cat.weight*10 as {cat.weight}, cat.name as {cat.name}"
    + "     from cat_log cat where {cat.mate} = :catId"
List loggedCats = sess.createSQLQuery(sql, "cat", Cat.class)
    .setLong("catId", catId)
    .list();

注意:明示的にプロパティを列挙するときは、クラスとそのサブクラスのすべてのプロパティを含めなければなりません!

13.3. 名前付きSQLクエリ

名前付きのクエリはマッピング・ドキュメントで定義することができ、名前付きHQLクエリと全く同じ方法でコールすることができます。

List people = sess.getNamedQuery("mySqlQuery")
    .setMaxResults(50)
    .list();
<sql-query name="mySqlQuery">
    <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 'Hiber%'
</sql-query>