Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to lazily fetch groups in JOOQ?

Tags:

java

stream

jooq

I'm trying to write a query in which I fetch child records for my aggregate root using leftJoin like this:

dslContext.select()
    .from(PARENT)
    .leftJoin(CHILD)
    .on(CHILD.PARENT_ID.eq(PARENT.ID))
    .stream()

My problem is that I need to use stream because there are a very big number of records but this way I can't use fetchGroups which I would normally use when I need parent-child records.

This is how I'd use fetchGroups:

dslContext.select()
    .from(PARENT)
    .leftJoin(CHILD)
    .on(CHILD.PARENT_ID.eq(PARENT.ID))
    .fetchGroups(Parent.class, Child.class)

which would create a nice Map<Parent, Child> for me.

I tried to collect using Collectors.groupingBy but it is not straightforward how to use it and the docs don't explain it either.

How can I fetch parent-child records in one go lazily?

like image 688
Adam Arold Avatar asked Jun 24 '19 12:06

Adam Arold


People also ask

What are the different fetching modes in jOOQ?

Just to name a few, here are some of jOOQ's fetching modes: Untyped vs. typed fetching: Sometimes you care about the returned type of your records, sometimes (with arbitrary projections) you don't.

How to fetch Records one-by-one or in small chunks in jOOQ?

If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a org.jooq.Cursor type for that purpose. In order to obtain such a reference, use the ResultQuery.fetchLazy () method. An example is given here:

How do I use jOOQ for reactive programming?

Fetching data reactively: In a reactive programming model, you will want to fetch results from a publisher into a subscription. jOOQ implements different Publisher APIs. The term "fetch" is always reused in jOOQ when you can fetch data from the database. An org.jooq.ResultQuery provides many overloaded means of fetching data:

What is jOOQ?

1. Introduction In this tutorial, we're going to take a quick tour of running an application with jOOQ (Java Object Orientated Query). This library generates Java classes based on the database tables and lets us create type-safe SQL queries through its fluent API.


1 Answers

In jOOQ 3.11, we have added a new ResultQuery.collect() method, and we are planning on re-implementing most of our fetchXYZ() logic as standard Collector implementations, which can then be used with Stream to achieve exactly what you're looking for. The main driver for this is to avoid the proliferation of more of these fetchXYZ() overloads, and to offer more composability.

You can do it manually, of course:

Using Stream, in case you want to add additional operations to the stream pipeline

// Don't forget, this is a resourceful stream!
try (Stream<Record> stream = dslContext.select()
    .from(PARENT)
    .leftJoin(CHILD)
    .on(CHILD.PARENT_ID.eq(PARENT.ID))
    .stream()) {

    Map<Parent, List<Child>> result = stream.collect(
        Collectors.groupingBy(r -> r.into(Parent.class),
            Collectors.mapping(r -> r.into(Child.class), Collectors.toList())
        )
    );
}

The Javadoc of Collectors.groupingBy() has a similar example.

Using ResultQuery.collect(), if you don't need the stream pipeline.

Alternatively, using jOOQ 3.11's ResultQuery.collect()

Map<Parent, List<Child>> result = dslContext
    .select()
    .from(PARENT)
    .leftJoin(CHILD)
    .on(CHILD.PARENT_ID.eq(PARENT.ID))
    .collect(
        Collectors.groupingBy(r -> r.into(Parent.class),
            Collectors.mapping(r -> r.into(Child.class), Collectors.toList())
        )
    );
like image 182
Lukas Eder Avatar answered Sep 19 '22 23:09

Lukas Eder