[解決済み] Spring Data JPA GROUP BY クエリからカスタムオブジェクトを返す方法
2022-04-29 12:45:03
質問
Spring Data JPAを使用したSpring Bootアプリケーションを開発しています。カスタムJPQLクエリを使用して、いくつかのフィールドでグループ化し、カウントを取得しています。以下は私のリポジトリメソッドです。
@Query(value = "select count(v) as cnt, v.answer from Survey v group by v.answer")
public List<?> findSurveyCount();
正常に動作し、以下のような結果が得られました。
[
[1, "a1"],
[2, "a2"]
]
このようなものが欲しいのですが。
[
{ "cnt":1, "answer":"a1" },
{ "cnt":2, "answer":"a2" }
]
どうすれば実現できるのでしょうか?
どのように解決するのですか?
JPQLクエリーの解決方法
内のJPQLクエリに対応しています。 JPA仕様 .
ステップ1 : シンプルなビーンクラスを宣言する
package com.path.to;
public class SurveyAnswerStatistics {
private String answer;
private Long cnt;
public SurveyAnswerStatistics(String answer, Long cnt) {
this.answer = answer;
this.count = cnt;
}
}
ステップ2 : リポジトリメソッドからビーンインスタンスを返す
public interface SurveyRepository extends CrudRepository<Survey, Long> {
@Query("SELECT " +
" new com.path.to.SurveyAnswerStatistics(v.answer, COUNT(v)) " +
"FROM " +
" Survey v " +
"GROUP BY " +
" v.answer")
List<SurveyAnswerStatistics> findSurveyCount();
}
重要なお知らせ
-
パッケージ名を含む、Bean クラスへの完全修飾パスを必ず指定してください。たとえば、ビーン・クラスの名前が
MyBean
で、パッケージcom.path.to
の場合、ビーンへの完全修飾パスは次のようになります。com.path.to.MyBean
. 単にMyBean
は動作しません (ビーンクラスがデフォルトパッケージ内にある場合を除く)。 -
ビーンクラスのコンストラクタを呼び出すには、必ず
new
キーワードを使用します。SELECT new com.path.to.MyBean(...)
は動作しますがSELECT com.path.to.MyBean(...)
となります。 - ビーンコンストラクタで予想される順序と全く同じ順序で属性を渡すことを確認してください。異なる順番で属性を渡そうとすると、例外が発生します。
-
クエリが有効なJPAクエリであること、つまりネイティブクエリでないことを確認してください。
@Query("SELECT ...")
または@Query(value = "SELECT ...")
または@Query(value = "SELECT ...", nativeQuery = false)
は動作しますが@Query(value = "SELECT ...", nativeQuery = true)
は動作しません。これは、ネイティブクエリがJPAプロバイダに変更されずに渡され、そのまま基盤となるRDBMSに対して実行されるからです。したがってnew
とcom.path.to.MyBean
が有効な SQL キーワードでない場合、RDBMS は例外をスローします。
ネイティブクエリの解決策
上述したように
new ...
構文はJPAがサポートするメカニズムであり、すべてのJPAプロバイダで機能します。しかし、クエリ自体がJPAクエリでない場合、つまりネイティブクエリである場合は
new ...
構文が使えないのは、クエリが直接基盤となる RDBMS に渡されるからです。
new
キーワードは標準SQLの一部ではないので、このキーワードを使用することはできません。
このような状況では、ビーンクラスを Springデータプロジェクション のインターフェイスを使用します。
ステップ1 : プロジェクション・インターフェースを宣言する
package com.path.to;
public interface SurveyAnswerStatistics {
String getAnswer();
int getCnt();
}
ステップ2 : クエリから投影されたプロパティを返す
public interface SurveyRepository extends CrudRepository<Survey, Long> {
@Query(nativeQuery = true, value =
"SELECT " +
" v.answer AS answer, COUNT(v) AS cnt " +
"FROM " +
" Survey v " +
"GROUP BY " +
" v.answer")
List<SurveyAnswerStatistics> findSurveyCount();
}
SQLを使用する
AS
キーワードを使用して、結果フィールドをプロジェクションプロパティにマッピングし、曖昧さのないマッピングを実現します。
関連
-
[解決済み] Spring Data JPAにおけるCrudRepositoryとJpaRepositoryのインターフェースの違いは何ですか?
-
undefinedeclipse エラー。この行に複数のアノテーションが見つかりました: - 文字列を型解決に解決できない
-
アクセス制限です。タイプ 'Application' は API ではありません。
-
スキャナは、タイプに解決することはできません最もルーキー初心者の質問
-
Eclipseプロンプトを実行する java仮想マシンを使用しない
-
エラーの解決方法 jarfile XXX.jarにアクセスできません。
-
linux run jarfile Invalid or corrupt jarfile error.
-
Error: java.lang.NoClassDefFoundError: クラス XXXX を初期化できませんでした
-
このラインで複数のマーカーを解決する方法
-
ブラウザでの大容量ファイルスライスアップロード(Javaサーバサイド実装)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
この行に複数のマーカーがある - HttpServletResponseが型エラーに解決できない
-
undefinedeclipse エラー。この行に複数のアノテーションが見つかりました: - 文字列を型解決に解決できない
-
ファインバグタイプ
-
Enumとの組み合わせでswitchの使い方を一度覚えるために必要な定数式
-
Intellij IDEAのエラー「CreateProcess error=2, system could not find specified file」に対する完璧な解決策です。
-
eclipseにプロジェクトをインポートした後、Editorにmain typeが含まれない問題
-
spring aop アドバイスからの Null 戻り値が、サマリーのプリミティブ戻り値と一致しない。
-
javaでクラスを作成すると、enclosing classでないように見える
-
Error: java.lang.NoClassDefFoundError: クラス XXXX を初期化できませんでした
-
Exception: java.util.NoSuchElementException: 行が見つかりません