sql >> Database >  >> RDS >> Mysql

jooq enkele query met een-op-veel-relatie

Er zijn veel manieren om een ​​geneste collectie te materialiseren met SQL en/of met jOOQ. Ik ga er gewoon een paar door:

Joins gebruiken

Als u die collecties niet diep nest, denormaliseert (afvlakt) uw resultaten met een JOIN kan het voor u doen, zonder al te veel overhead toe te voegen omdat gegevens worden gedupliceerd. In wezen schrijf je:

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

De bovenstaande kaart bevat experimentrecords als sleutels en geneste verzamelingen die alle tags als waarden bevatten.

Twee zoekopdrachten maken

Als u een complexe objectgrafiek wilt materialiseren, is het gebruik van joins mogelijk niet langer optimaal. In plaats daarvan wilt u waarschijnlijk de gegevens in uw cliënt uit twee verschillende zoekopdrachten verzamelen:

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

En

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

En voeg nu de twee resultaten samen in het geheugen van uw cliënt, bijvoorbeeld

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

Verzamelingen nesten met SQL/XML of SQL/JSON

Deze vraag was niet vereist, maar anderen zullen deze vraag misschien vinden op zoek naar een manier om veel relaties met jOOQ te nesten. Ik heb hier een antwoord gegeven . Vanaf jOOQ 3.14 kunt u de SQL/XML- of SQL/JSON-mogelijkheden van uw RDBMS gebruiken en vervolgens Jackson, Gson of JAXB gebruiken om verzamelingen als volgt te nesten:

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

Waar Experiment is een aangepaste Java-klasse zoals deze:

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

class Tag {
  long id;
  String name;
}

Verzamelingen nesten met MULTISET

Zelfs beter dan het bovenstaande, u kunt zich verbergen met SQL/XML of SQL/JSON achter de nieuwe MULTISET van jOOQ 3.15 operatorondersteuning . Ervan uitgaande dat de bovenstaande Java-klassen Java 16-records zijn (of andere onveranderlijke klassen), kunt u zelfs geneste verzamelingen veilig toewijzen aan uw DTO's:

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

Waar Experiment is een aangepaste Java-klasse zoals deze:

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

Zie ook deze blogpost voor meer informatie .



  1. 3 manieren om rijen te retourneren die alfanumerieke tekens bevatten in SQL Server

  2. Vind de rangorde van een geheel getal in mysql

  3. Snel een primaire sleutelbeperking vinden in SQL Server 2005

  4. Gegevens uit opgeslagen procedures SELECTEREN