2.3.2. ネイティブクエリのマッピング

また、ネイティブクエリ (つまり、プレーンな SQL クエリ) をマップすることもできます。これを実現するには、 @SqlResultSetMapping (複数の結果セットマッピングを定義する場合は @SqlResultSetMappings) を使用して SQL 結果セット構造を定義する必要があります。@NamedQuery と同様に、@SqlResultSetMapping はクラスレベルまたは JPA XML ファイルで定義できます。ただし、そのスコープはアプリケーションに対してグローバルになります。
示されたように、resultSetMapping パラメータは @NamedNativeQuery で定義され、定義された @SqlResultSetMapping の名前を表します。結果セットマッピングはこのネイティブクエリによって取得されたエンティティを宣言します。エンティティの各フィールドは SQL エイリアス (またはカラム名) にバインドされます。サブクラスのフィールドを含むエンティティのすべてのフィールドと、関連するエンティティの外部キーカラムは SQL クエリに存在する必要があります。フィールドはクラスプロパティで宣言されたのと同じカラム名にマップされるため、フィールド定義はオプションです。
@NamedNativeQuery(name="night&area", query="select night.id nid, night.night_duration, "
      + " night.night_date, area.id aid, night.area_id, area.name " + "from Night night, Area area where night.area_id =
      area.id", resultSetMapping="joinMapping")
      @SqlResultSetMapping(name="joinMapping", entities={
      @EntityResult(entityClass=org.hibernate.test.annotations.query.Night.class, fields = { @FieldResult(name="id",
      column="nid"), @FieldResult(name="duration", column="night_duration"), @FieldResult(name="date",
      column="night_date"), @FieldResult(name="area", column="area_id"), discriminatorColumn="disc" }),
      @EntityResult(entityClass=org.hibernate.test.annotations.query.Area.class, fields = { @FieldResult(name="id",
      column="aid"), @FieldResult(name="name", column="name") }) } )
上記の例では、night&area 名前付きクエリは joinMapping 結果セットマッピングを使用します。このマッピングは NightArea の 2 つのエンティティを返します。各プロパティは宣言され、カラム名 (クエリにより実際に取得されたカラム名) に関連付けられます。プロパティ/カラムの暗黙的な宣言について説明します。
@Entity
      @SqlResultSetMapping(name="implicit", entities=@EntityResult(entityClass=org.hibernate.test.annotations.query.SpaceShip.class)) @NamedNativeQuery(name="implicitSample", query="select * from SpaceShip", resultSetMapping="implicit")
public class SpaceShip {
    private String name;
    private String model;
    private double speed;

    @Id
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name="model_txt")
    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public double getSpeed() {
        return speed;
    }

    public void setSpeed(double speed) {
        this.speed = speed;
    }
}
この例では、結果セットマッピングのエンティティメンバのみを定義します。In this example, we only describe the entity member of the result set プロパティとカラムのマッピングはエンティティマッピング値を使用して行われます。この場合は、model プロパティが model_txt カラムにバインドされます。関連するエンティティに対する関係で複合プライマリキーを使用する場合は、各外部キーカラムに対して @FieldResult エレメントを使用する必要があります。@FieldResult 名は関係のプロパティ名、ドット (".")、プライマリキーの名前、フィールド、またはプロパティを結合したものです。
@Entity
@SqlResultSetMapping(name="compositekey",
        entities=@EntityResult(entityClass=org.hibernate.test.annotations.query.SpaceShip.class,
            fields = {
                    @FieldResult(name="name", column = "name"),
                    @FieldResult(name="model", column = "model"),
                    @FieldResult(name="speed", column = "speed"),
 @FieldResult(name="captain.firstname", column = "firstn"), @FieldResult(name="captain.lastname", column = "lastn"),
                    @FieldResult(name="dimensions.length", column = "length"),
                    @FieldResult(name="dimensions.width", column = "width")
                    }),
        columns = { @ColumnResult(name = "surface"),
                    @ColumnResult(name = "volume") } )

@NamedNativeQuery(name="compositekey",
    query="select name, model, speed, lname as lastn, fname as firstn, length, width, length * width as surface from SpaceShip", 
    resultSetMapping="compositekey")
} )
public class SpaceShip {
    private String name;
    private String model;
    private double speed;
    private Captain captain;
    private Dimensions dimensions;

    @Id
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @ManyToOne(fetch= FetchType.LAZY)
    @JoinColumns( {
            @JoinColumn(name="fname", referencedColumnName = "firstname"),
            @JoinColumn(name="lname", referencedColumnName = "lastname")
            } )
    public Captain getCaptain() {
        return captain;
    }

    public void setCaptain(Captain captain) {
        this.captain = captain;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public double getSpeed() {
        return speed;
    }

    public void setSpeed(double speed) {
        this.speed = speed;
    }

    public Dimensions getDimensions() {
        return dimensions;
    }

    public void setDimensions(Dimensions dimensions) {
        this.dimensions = dimensions;
    }
}

@Entity
@IdClass(Identity.class)
public class Captain implements Serializable {
    private String firstname;
    private String lastname;

    @Id
    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    @Id
    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }
}

注記

寸法プロパティを見ると、Hibernate が組み込みオブジェクトに対してドット表記法をサポートすることがわかります (組み込みオブジェクトをネストすることもできます)。ただし、EJB3 実装はこの機能をサポートする必要はありません。
単一のエンティティを取得する場合やデフォルトのマッピングを使用する場合は、resultSetMapping の代わりに resultClass 属性を使用できます。
@NamedNativeQuery(name="implicitSample", query="select * from SpaceShip", resultClass=SpaceShip.class)
public class SpaceShip {
一部のネイティブクエリでは、レポートクエリを構築するときなどにスカラー値を返す必要があります。クエリは @ColumnResult を使用して @SqlResultsetMapping でマップできます。実際には同じネイティブクエリでエンティティとスカラーの戻り値を同時に使用することもできます (ただし、これは一般的ではない可能性があります)。
@SqlResultSetMapping(name="scalar", columns=@ColumnResult(name="dimension")) @NamedNativeQuery(name="scalar", query="select length*width as dimension from SpaceShip", resultSetMapping="scalar")
ネイティブクエリに固有な他のクエリヒントが導入されました (クエリがストアドプロシージャであるかどうかに応じて true または false になる org.hibernate.callable)。