技術メモブログ

技術ネタの備忘録的なブログ。技術ネタ以外にも気になったことをつらつら書きます

ResultSetMapping(Contstructor Result Mapping) の使い方

JPA ResultSetMappingのメモ

DB からデータを取得するとき、2つのテーブルを結合してそれぞれのテーブルから
データを絞って取得したいときはよくあること。
例えば↓みたいなテーブルがあって

艦船

艦名 工廠
大和 1
陸奥 2
海風 4

工廠

ID 工廠名
1
2 横須賀
3 佐世保
4 舞鶴

こんな結果が欲しい

結果表

艦名 工廠
大和
陸奥 横須賀
海風 舞鶴

Native SQL、JPQL 的には

SELECT 艦名, 工廠名 FROM 艦船 INNER JOIN 工廠 ON 艦船.工廠 = 工廠.ID

しかし普通に実行した結果だと Object 型のリストになる。
(上記だと、3レコード分 Object のリストで、カラム分で更に2つのリスト)

これをわかりやすく自分で定義したクラスで取得したい時は、ResultSetMapping を使えば可能となる。

以下のような設定

●eclipselonk-orm.xml

<sql-result-set-mapping name="buttleShip" >
    <constructor-result target-class="hoge.fuge.ButtleShip">
        <column name="shipName" />   ←ここと
        <column name="arsenalName"/>
    </constructor-result>
</sql-result-set-mapping>

<named-native-query name="findButtleShip" result-set-mapping="buttleShip">
    <query>
        <![CDATA[
        SELECT
            艦名 shipName,      ←ここは合わせないとエラる
            工廠 arsenalName
        FROM
            艦船
        INNER JOIN
            工廠
        ON
            艦船.工廠 = 工廠.ID
        ]]>
    </query>
</named-native-query>

 
POJO

@Getter
@Setter
@AllArgsConstructor
public class ButtleShip
{
    private String shipName;
    private String arsenalName;
}

lombok 使った記述にしてます)

ちなみに、SQLの実行時に戻りとなる POJO のクラスを指定しないと Objectで返ってくる
素の記述だと、これに時に設定となるかな

entityManager.createNamedQuery( queryName, resultClass );

POJO ではコンストラクタを指定しないと、SQL 実行時にエラーになる
使用している仕組みが Constructor Result Mapping というだけあって、コンストラクタで値を設定しているもよう

Constructor Result Mappings は JPA 2.1 から使えるようになったみたいなので、
それ以前の場合は注意が必要
参考にしたのはここ