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 .