Tuesday, September 27, 2022
HomeJavaTips on how to Typesafely Map a Nested SQL Assortment right into...

Tips on how to Typesafely Map a Nested SQL Assortment right into a Nested Java Map with jOOQ – Java, SQL and jOOQ.


A very cool, current query on Stack Overflow was about find out how to map a nested assortment right into a Java Map with jOOQ. Previously, I’ve blogged concerning the highly effective MULTISET operator many occasions, which permits for nesting collections in jOOQ. This time, as a substitute of nesting information right into a Record<UserType>, why not nest it in a Map<UserType1, UserType2> as a substitute?

Trying on the Sakila database, let’s take a look at how we will fetch information into this Java report kind:

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

The end result kind ought to wrap up the FILM.TITLE together with the sum of money or DVD rental retailer made on every day, per movie. We may use different information buildings, however let’s assume that is what we wish to eat within the UI or service or no matter.

In jOOQ, as ever so typically, due to MULTISET, we will do it in a single question that appears like this:

Record<Movie> end result =
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<Consequence<Record2<LocalDate, BigDecimal>>>
        // to Subject<Map<LocalDate, BigDecimal>>
        .convertFrom(r -> r.acquire(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 end result, e.g. like this:

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

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

To provide:

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 part is, as all the time with jOOQ, fully kind protected! Attempt it your self, change a few of the column expressions within the question, or the ensuing report or Map kind to see that the question will cease compiling!

The fascinating bit right here is:

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

The Subject.convertFrom() technique 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<Consequence<Record2<LocalDate, BigDecimal>>> (the multiset discipline kind)
  • To Subject<Map<LocalDate, BigDecimal>> (the mapped kind)

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

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

That particular utilization of generics permits for avoiding the repetition of the important thing and worth expressions of the sphere, realizing {that a} assortment of Record2<Okay, V> has an apparent technique to acquire right into a Map<Okay, V> (or Map<Okay, Record<V>> when you’re utilizing Information.intoGroups(), if keys could 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, while you’re utilizing jOOQ 3.15’s new nesting capabilities for nested collections (MULTISET or MULTISET_AGG) or nested information (ROW). Along with ad-hoc converters, you may map the jOOQ illustration into any Java illustration in the midst of your question, to stick to any goal kind of your selecting, together with nested Map<Okay, V>, with arbitrary kinds of Okay and V

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments