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

1対多の関係を持つjooq単一クエリ

    ネストされたコレクションをSQLやjOOQで実体化する方法はたくさんあります。私はそれらのいくつかを通過しているだけです:

    結合の使用

    これらのコレクションを深くネストしない場合は、JOINを使用して結果を非正規化(フラット化)します。 データが複製されているため、オーバーヘッドをあまり追加せずに、トリックを実行できる可能性があります。基本的に、次のように記述します。

    Map<ExperimentRecord, Result<Record>> map =
    DSL.using(configuration)
       .select()
       .from(EXPERIMENT)
       .join(TAGS)
       .on(...)
       .fetchGroups(EXPERIMENT);
    

    上記のマップには、キーとして実験レコードが含まれ、値としてすべてのタグを含むネストされたコレクションが含まれています。

    2つのクエリを作成する

    複雑なオブジェクトグラフを具体化する場合は、結合の使用が最適ではなくなる可能性があります。代わりに、2つの異なるクエリからクライアントのデータを収集することをお勧めします。

    Result<ExperimentRecord> experiments = 
    DSL.using(configuration)
       .selectFrom(EXPERIMENT)
       .fetch();
    

    そして

    Result<TagsRecord> tags =
    DSL.using(configuration)
       .selectFrom(TAGS)
       .where(... restrict to the previous experiments ...)
       .fetch();
     
    

    そして今、2つの結果をクライアントのメモリにマージします。例:

    experiments.stream()
               .map(e -> new ExperimentWithTags(
                    e, 
                    tags.stream()
                        .filter(t -> e.getId().equals(t.getExperimentId()))
                        .collect(Collectors.toList())
               ));
    

    SQL/XMLまたはSQL/JSONを使用したコレクションのネスト

    この質問はそれを必要としませんでしたが、他の人はjOOQとの多くの関係をネストする方法を探してこの質問を見つけるかもしれません。 ここに回答を提供しました 。 jOOQ 3.14以降では、RDBMSのSQL/XMLまたはSQL/JSON機能を使用してから、Jackson、Gson、またはJAXBを使用して次のようなコレクションをネストできます。

    List<Experiment> experiments =
    ctx.select(
          EXPERIMENT.asterisk(),
          field(
            select(jsonArrayAgg(jsonObject(TAGS.fields())))
            .from(TAGS)
            .where(TAGS.EXPERIMENT_ID.eq(EXPERIMENT.ID))
          ).as("tags")
        )
       .from(EXPERIMENT)
       .fetchInto(Experiment.class);
    

    Experimentの場所 は次のようなカスタムJavaクラスです:

    class Experiment {
      long id;
      String name;
      List<Tag> tags;
    }
    
    class Tag {
      long id;
      String name;
    }
    

    MULTISETを使用したコレクションのネスト

    上記よりもさらに優れているのは、 jOOQ3.15の新しいMULTISETの背後でSQL/XMLまたはSQL/JSONを使用して非表示にすることができます オペレーターサポート 。上記のJavaクラスがJava16レコード(またはその他の不変クラス)であると仮定すると、ネストされたコレクションタイプをDT​​Oに安全にマップすることもできます。

    List<Experiment> experiments =
    ctx.select(
          EXPERIMENT.ID,
          EXPERIMENT.NAME,
          multiset(
            select(TAGS.ID, TAGS.NAME)
            .from(TAGS)
            .where(TAGS.EXPERIMENT_ID.eq(EXPERIMENT.ID))
          ).as("tags").convertFrom(r -> r.map(Records.mapping(Tag::new)))
        )
       .from(EXPERIMENT)
       .fetch(Records.mapping(Experiment::new));
    

    Experimentの場所 は次のようなカスタムJavaクラスです:

    record Experiment(long id, String name, List<Tag> tags) {}
    record Tag(long id, String name) {}
    

    詳細については、このブログ投稿も参照してください



    1. mySQLでLimitを動的に変更する方法

    2. XamppとMySQLが起動していません

    3. SQLServerで現在の日時から過去7日間までの過去7日間のデータを取得する方法

    4. 指定されたテーブルの動的な列のセットを返す関数