sql >> データベース >  >> RDS >> Mysql

Jooqでの1対多の選択

    JOINの使用 これでは機能しません。

    この方法で結合を使用している場合は、デカルト積を作成しているため、クエリはかなり非効率になります。 BooksとArticlesテーブルの間で、意味のないすべての組み合わせを重複排除する前に、データベースとJavaクライアントの両方でかなりのメモリとCPUの消費が発生します。

    「正しい」SQLアプローチは、 MULTISET この記事で説明されているように 。残念ながら、jOOQ3.9はMULTISETをサポートしていません まだ (多くのデータベースもありません)。したがって、2つの別々のクエリを作成する必要があります:

    1. すべての本を取得する
    2. すべての記事を取得する

    次に、Java 8 Streamsのようなものを使用して、それらを単一のオブジェクトにマップします。

    MULTISETの使用 jOOQ3.15以降

    幸い、jOOQ 3.15以降、MULTISETを使用してSQLでコレクションをネストするためのすぐに使用できるソリューションがあります。 。クエリは次のようになります:

    リフレクションの使用

    List<Author> authors =
    ctx.select(
          AUTHOR.ID,
          AUTHOR.NAME,
          multiset(
            select(BOOKS.TITLE)
            .from(BOOKS)
            .where(BOOKS.AUTHOR_ID.eq(AUTHOR.ID))
          ).as("books"),
          multiset(
            select(ARTICLES.TITLE)
            .from(ARTICLES)
            .where(ARTICLES.AUTHOR_ID.eq(AUTHOR.ID))
          ).as("articles")
        )
       .from(AUTHOR)
       .where(AUTHOR.ID.eq(id))
       .fetchInto(Author.class);
    

    タイプセーフを使用して、 ad -ホック変換

    List<Author> authors =
    ctx.select(
          AUTHOR.ID,
          AUTHOR.NAME,
          multiset(
            select(BOOKS.TITLE)
            .from(BOOKS)
            .where(BOOKS.AUTHOR_ID.eq(AUTHOR.ID))
          ).as("books").convertFrom(r -> r.map(Record1::value1)),
          multiset(
            select(ARTICLES.TITLE)
            .from(ARTICLES)
            .where(ARTICLES.AUTHOR_ID.eq(AUTHOR.ID))
          ).as("articles").convertFrom(r -> r.map(Record1::value1))
        )
       .from(AUTHOR)
       .where(AUTHOR.ID.eq(id))
       .fetch(Records.mapping(Author::new));
    

    MULTISETの詳細 、このブログ投稿を参照してください 、または手動セクション:

    jOOQ3.14以降のSQL/XMLまたはSQL/JSONの使用

    jOOQ 3.14以降、RDBMSがサポートしている場合は、SQL/XMLまたはSQL/JSONを介してコレクションをネストできます。ドキュメントを作成してから、Gson、Jackson、JAXBなどを使用してJavaクラスにマップし直すことができます。例:

    List<Author> authors =
    ctx.select(
          AUTHOR.ID,
          AUTHOR.NAME,
          field(
            select(jsonArrayAgg(BOOKS.TITLE))
            .from(BOOKS)
            .where(BOOKS.AUTHOR_ID.eq(AUTHOR.ID))
          ).as("books"),
          field(
            select(jsonArrayAgg(ARTICLES.TITLE))
            .from(ARTICLES)
            .where(ARTICLES.AUTHOR_ID.eq(AUTHOR.ID))
          ).as("articles")
        )
       .from(AUTHOR)
       .where(AUTHOR.ID.eq(id))
       .fetchInto(Author.class);
    

    JSON_ARRAYAGG()に注意してください 空のセットをNULLに集約します 、空の[]ではありません 。 それが問題になる場合は、COALESCE()を使用してください




    1. JPAによる永続性のためのJavaサポートを理解する

    2. MySQL-where句で集計列を参照しています

    3. mysql_fetch_array()は、パラメーター1がリソースの問題であると想定しています

    4. LinuxでのDG40DBCデバッグツールとしてのstraceの使用