0

集計値を出力するカスタマイズ可能なクエリを作成したいと考えています。クエリを取得して実行する 3 つの方法を知っていますが、どれも十分ではないようです。作成したいクエリは次のようになります。

Select max(category), min(price) as minprice from mytable where k='v' group by category

tldr: 1 と 2 をスキップします。

  1. 文字列としての SQL
    • private NamedParameterJdbcTemplate template; template.query("select ..." , new MapSqlParameterSource("...", "...") , rs -> {...rs.getString("minprice")...
    • 長所: クエリから結果にアクセスできます
    • 短所: クエリ ビルダーを使用していません。"select..." 文字列を自分で作成する必要があります。
  2. リポジトリの使用
    • public interface MytableRepository extends CrudRepository<Mytable, Integer> { @Query("Select ...") public List<Object[]> findMinMaxPrice(@Param("myParam") String myParam);
    • 長所: クエリから結果にアクセスできます。
    • 短所: クエリがハードコーディングされている
  3. クエリ ビルダーの使用
    • Specification<MyTable> spec = Specifications.<>where((mytable, query, cb) -> { Predicate sql = cb.equal(mytable.get("k"), "v"; return sql; } List<Mytable> result = myJpaSpecificationExecutor.findall(spec);
    • 長所:クエリビルダーを使用しています
    • 短所: クエリは groupBy を使用していません。groupBy クエリはクラスのレコードではMytableなく集計値を返すため、これを機能させる方法がわかりません。から選択を開始するMytableので、それを型パラメーター to として使用する必要があると思いますがSpecification、それはすぐに結果も型MyTableにする必要があることを意味しますね。

柔軟な結果タイプでクエリビルダーを使用するにはどうすればよいですか?

4

2 に答える 2

1

jOOQ を調べることを検討することもできます。これにより、いわばクエリを「コード内」に保ちながら、必要なだけ柔軟性が得られます。

データベース スキーマから Java クラスを生成できます。これを使用して、DSL を使用してクエリを作成できます。例を次に示します: https://github.com/benjamin-bader/droptools/blob/master/droptools-example/src/main/java/com/bendb/example/resources/PostsResource.java#L99

上記でリンクしたコードの内容は次のとおりです。

    final Record4<Integer, String, OffsetDateTime, String[]> record = create
            .select(BLOG_POST.ID, BLOG_POST.BODY, BLOG_POST.CREATED_AT, arrayAgg(POST_TAG.TAG_NAME))
            .from(BLOG_POST)
            .leftOuterJoin(POST_TAG)
            .on(BLOG_POST.ID.equal(POST_TAG.POST_ID))
            .where(BLOG_POST.ID.equal(id.get()))
            .groupBy(BLOG_POST.ID, BLOG_POST.BODY, BLOG_POST.CREATED_AT)
            .fetchOne();

少しファンキーに見えますが、生成されるものは次のとおりです。

SELECT blog_post.id, blog_post.body, blog_post.created_at, array_agg(post_tag.tags)
FROM blog_post
LEFT JOIN post_tag ON blog_post.id = post_tag.post_id
WHERE blog_post.id = ?
GROUP BY blog_post.id, blog_post.body, blog_post.created_at

Java コードが生成された SQL を厳密に反映していることがわかりますが、jOOQ の生成されたコードのおかげで、依然として完全にタイプセーフです。これはコードであるため、必要に応じてクエリを動的に構築できます。

これは大きな依存関係ですが、SQL のニーズが特殊化または動的である場合は、多くのことを実行できます。

于 2019-05-17T21:13:40.857 に答える