[ad_1]
A very cool, latest query on Stack Overflow was about find out how to map a nested assortment right into a Java Map
with jOOQ. Prior to now, I’ve blogged concerning the highly effective MULTISET
operator many occasions, which permits for nesting collections in jOOQ. This time, as an alternative of nesting knowledge right into a Listing<UserType>
, why not nest it in a Map<UserType1, UserType2>
as an alternative?
Wanting on the Sakila database, let’s take a look at how we will fetch knowledge into this Java report
sort:
report Movie(
String title,
Map<LocalDate, BigDecimal> income
) {}
The outcome sort ought to wrap up the FILM.TITLE
together with the sum of money or DVD rental retailer made on every day, per movie. We might use different knowledge constructions, however let’s assume that is what we wish 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:
Listing<Movie> outcome =
ctx.choose(
FILM.TITLE,
multiset(
choose(
PAYMENT.PAYMENT_DATE.solid(LOCALDATE),
sum(PAYMENT.AMOUNT))
.from(PAYMENT)
.the place(PAYMENT.rental().stock().FILM_ID
.eq(FILM.FILM_ID))
.groupBy(PAYMENT.PAYMENT_DATE.solid(LOCALDATE))
.orderBy(PAYMENT.PAYMENT_DATE.solid(LOCALDATE))
)
// Convert Discipline<Consequence<Record2<LocalDate, BigDecimal>>>
// to Discipline<Map<LocalDate, BigDecimal>>
.convertFrom(r -> r.gather(Data.intoMap())
)
.from(FILM)
.orderBy(FILM.TITLE)
// Convert Record2<String, Map<LocalDate, BigDecimal>>
// to Listing<Movie>
.fetch(Data.mapping(Movie::new))
We will then eat the outcome, e.g. like this:
for (Movie movie : outcome) {
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 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 thing is, as all the time with jOOQ, fully 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.gather(Data.intoMap())
The Discipline.convertFrom()
technique is from jOOQ 3.15’s new ad-hoc conversion API, which permits for ad-hoc changing a Discipline<T>
column expression to a Discipline<U>
column expression. On this case, the conversion goes:
- From
Discipline<Consequence<Record2<LocalDate, BigDecimal>>>
(the multiset area sort) - To
Discipline<Map<LocalDate, BigDecimal>>
(the mapped sort)
It does so by accumulating all of the Record2<LocalDate, BigDecimal>
information of the nested assortment right into a Map<LocalDate, BigDecimal>
utilizing the Data.intoMap()
collector. The signature of that technique is:
public static last <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 sector, realizing {that a} assortment of Record2<Okay, V>
has an apparent approach to gather right into a Map<Okay, V>
(or Map<Okay, Listing<V>>
should you’re utilizing Data.intoGroups()
, if keys might 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, once 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 sort of your selecting, together with nested Map<Okay, V>
, with arbitrary kinds of Okay
and V
[ad_2]