Mysql
 sql >> Baza danych >  >> RDS >> Mysql

pojedyncze zapytanie jooq z relacją jeden do wielu

Istnieje wiele sposobów na zmaterializowanie zagnieżdżonej kolekcji za pomocą SQL i/lub jOOQ. Przeglądam tylko niektóre z nich:

Korzystanie z połączeń

Jeśli nie zagnieżdżasz głęboko tych kolekcji, denormalizujesz (spłaszczasz) wyniki za pomocą JOIN może załatwić sprawę za Ciebie, nie obciążając zbytnio duplikowaniem danych. Zasadniczo napiszesz:

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

Powyższa mapa zawiera rekordy eksperymentu jako klucze i zagnieżdżone kolekcje zawierające wszystkie tagi jako wartości.

Tworzenie dwóch zapytań

Jeśli chcesz zmaterializować złożony graf obiektów, użycie złączeń może nie być już optymalne. Zamiast tego prawdopodobnie chcesz zebrać dane w swoim kliencie z dwóch różnych zapytań:

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

I

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

A teraz połącz oba wyniki w pamięci klienta, np.

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

Zagnieżdżanie kolekcji przy użyciu SQL/XML lub SQL/JSON

To pytanie nie wymagało tego, ale inni mogą znaleźć to pytanie w poszukiwaniu sposobu na zagnieżdżenie wielu relacji z jOOQ. Podałem odpowiedź tutaj . Począwszy od jOOQ 3.14, możesz użyć możliwości SQL/XML lub SQL/JSON swojego RDBMS, a następnie użyć Jacksona, Gson lub JAXB do zagnieżdżenia kolekcji w następujący sposób:

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);

Gdzie Experiment to niestandardowa klasa Java, taka jak ta:

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

class Tag {
  long id;
  String name;
}

Zagnieżdżanie kolekcji przy użyciu MULTISET

Jeszcze lepsze niż powyższe, możesz ukryć się za pomocą SQL/XML lub SQL/JSON za nowym MULTISET jOOQ 3.15 wsparcie operatora . Zakładając, że powyższe klasy Javy są rekordami Javy 16 (lub innymi niezmiennymi klasami), możesz nawet bezpiecznie mapować zagnieżdżone kolekcje typu do swoich DTO:

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));

Gdzie Experiment to niestandardowa klasa Java, taka jak ta:

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

Zobacz także ten wpis na blogu, aby uzyskać więcej informacji .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL — pobierz wynik tylko z bieżącego roku

  2. Haversine i Laravel

  3. Jak przekonwertować format daty csv na mysql db

  4. Trafność wyszukiwania pełnotekstowego jest mierzona w?

  5. mysql zapytanie PHP:chcę, aby określone elementy były najpierw, a następnie posortować resztę elementów