Thursday, March 23, 2023
HomeJavaHow you can Typesafely Map a Nested SQL Assortment right into a...

How you can Typesafely Map a Nested SQL Assortment right into a Nested Java Map with jOOQ – Java, SQL and jOOQ.


A extremely cool, latest query on Stack Overflow was about how one can map a nested assortment right into a Java Map with jOOQ. Up to now, I’ve blogged in regards to the highly effective MULTISET operator many instances, which permits for nesting collections in jOOQ. This time, as a substitute of nesting knowledge right into a Record<UserType>, why not nest it in a Map<UserType1, UserType2> as a substitute?

Trying on the Sakila database, let’s have a look at how we will fetch knowledge into this Java report sort:

report Movie(
    String title,
    Map<LocalDate, BigDecimal> income
) {}

The consequence sort ought to wrap up the FILM.TITLE together with the amount of cash or DVD rental retailer made on every day, per movie. We may use different knowledge buildings, however let’s assume that is what we need to eat within the UI or service or no matter.

In jOOQ, as ever so usually, because of MULTISET, we will do it in a single question that appears like this:

Record<Movie> consequence =
ctx.choose(
        FILM.TITLE,
        multiset(
            choose(
                PAYMENT.PAYMENT_DATE.forged(LOCALDATE), 
                sum(PAYMENT.AMOUNT))
            .from(PAYMENT)
            .the place(PAYMENT.rental().stock().FILM_ID
                .eq(FILM.FILM_ID))
            .groupBy(PAYMENT.PAYMENT_DATE.forged(LOCALDATE))
            .orderBy(PAYMENT.PAYMENT_DATE.forged(LOCALDATE))
        )
        // Convert Subject<Outcome<Record2<LocalDate, BigDecimal>>>
        // to Subject<Map<LocalDate, BigDecimal>>
        .convertFrom(r -> r.accumulate(Information.intoMap())
   )
   .from(FILM)
   .orderBy(FILM.TITLE)

   // Convert Record2<String, Map<LocalDate, BigDecimal>>
   // to Record<Movie>
   .fetch(Information.mapping(Movie::new))

We are able to then eat the consequence, e.g. like this:

for (Movie movie : consequence) {
    System.out.println();
    System.out.println("Movie %s with income: "
        .formatted(movie.title()));

    // Inferred varieties are LocalDate d and BigDecimal r
    movie.income().forEach((d, r) -> 
        System.out.println("  %s: %s".formatted(d, r))
    );
}

To supply:

Movie ACADEMY DINOSAUR with income: 
  2005-05-27: 0.99
  2005-05-30: 1.99
  2005-06-15: 0.99
  [...]

Movie ACE GOLDFINGER with income: 
  2005-07-07: 4.99
  2005-07-28: 9.99
  2005-08-01: 4.99
  [...]

Every thing is, as all the time with jOOQ, utterly sort secure! Strive it your self, change a number of the column expressions within the question, or the ensuing report or Map sort to see that the question will cease compiling!

The attention-grabbing bit right here is:

.convertFrom(r -> r.accumulate(Information.intoMap())

The Subject.convertFrom() methodology is from jOOQ 3.15’s new ad-hoc conversion API, which permits for ad-hoc changing a Subject<T> column expression to a Subject<U> column expression. On this case, the conversion goes:

  • From Subject<Outcome<Record2<LocalDate, BigDecimal>>> (the multiset area sort)
  • To Subject<Map<LocalDate, BigDecimal>> (the mapped sort)

It does so by accumulating all of the Record2<LocalDate, BigDecimal> data of the nested assortment right into a Map<LocalDate, BigDecimal> utilizing the Information.intoMap() collector. The signature of that methodology is:

public static last <Ok, V, R entends Record2<Ok, V>> 
Collector<R, ?, Map<Ok, V>> intoMap() { ... }

That particular utilization of generics permits for avoiding the repetition of the important thing and worth expressions of the sphere, figuring out {that a} assortment of Record2<Ok, V> has an apparent technique to accumulate right into a Map<Ok, V> (or Map<Ok, Record<V>> when you’re utilizing Information.intoGroups(), if keys will be duplicate).

Notice that each of those collectors will produce an insertion order preserving Map (e.g. LinkedHashMap), such that any MULTISET ordering can be preserved.

Conclusion

The sky is the restrict, if you’re utilizing jOOQ 3.15’s new nesting capabilities for nested collections (MULTISET or MULTISET_AGG) or nested data (ROW). Along with ad-hoc converters, you possibly can map the jOOQ illustration into any Java illustration in the course of your question, to stick to any goal sort of your selecting, together with nested Map<Ok, V>, with arbitrary sorts of Ok and V

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments