🔖
【Spring Data JPA】SqlResultSetMappingとNamedNativeQueryの使い方メモ
概要
複数のテーブルを結合する際のSELECT文など、JPAの自動生成されるメソッドでは対応が困難な時があります。JPA(hibernate)のテーブルジョインの罠(n+1問題)にある通り、Entityどうしで結合関係を定義して取得することも不可能ではありませんが、やはり直接SELECT文を使いたい時はあると思います。
今回は対応の一つの方法としてSqlResultSetMapping
とNamedNativeQuery
を使って、Entityにデータを詰める方法を書いてみたいと思います。
使い方
SqlResultSetMappingのガイドの5.エンティティマッピング
に書いてある通り、@SqlResultSetMapping
にEntityのクラスとプロパティとカラムの紐付けを定義します。また、@NamedNativeQuery
にてSQL文を定義して、SqlResultSetMappingと紐付けをします。
また、How to Use Named Queries with Spring Data JPAの記事にある通り、RepositoryではNamedNativeQueryで定義した名前でメソッド名を定義します。
実装サンプル
実装サンプルとして、urlsテーブルとdomainsテーブルがあった時に、この2テーブルを結合して情報を取得する場合の例を紹介します。
Entity
@SqlResultSetMapping(
name = "siteInfoMap",
entities = {
@EntityResult(
entityClass= SiteInfo.class,
fields = {
// カラム名とプロパティ名を紐付け
@FieldResult(name="urlId", column="url_id"),
@FieldResult(name="url", column="url"),
@FieldResult(name="domainId", column="domain_id"),
@FieldResult(name="domain", column="domain")
}
)
}
)
@NamedNativeQuery(
name = "SiteInfo.getSiteInfo",
// SqlResultSetMappingで定義した名前
resultSetMapping = "siteInfoMap",
query = "select u.url_id, u.url, u.domain_id, d.domain from urls u inner join domains d on d.id = u.domain_id"
)
@Entity
public class SiteInfo {
@Id
private Long urlId;
private String url;
private Long domainId;
private String domain;
public SiteInfo(){}
public Long getUrlId() { return this.urlId; }
public void setUrlId(Long urlId) { this.urlId = urlId; }
public String getUrl() { return this.url; }
public void setUrl(String url) { this.url = url; }
public Long getDomainId() { return this.domainId; }
public void setDomainId(Long domainId) { this.domainId = domainId; }
public String getDomain() { return this.domain; }
public void setDomain(String domain) { this.domain = domain; }
}
Repositoryでは、上記で定義したクエリ名getSiteInfo
でメソッドの名前を定義します。
Repository
@Repository
public interface SiteInfoRepository extends JpaRepository<SiteInfo, String> {
List<SiteInfo> getSiteInfo();
}
Discussion