I know that to fetch into Map
I can use fetchMap
, but it doesn't support LinkedHashMap
, where I want to maintain the insertion order created by orderBy
.
I tried
.
.
.
.orderBy(...)
.collect(
Collectors.toMap(
record -> record.field1(),
record -> record.field2(),
LinkedHashMap.class));
but the field1
and field2
parts gave me the following error.
Cannot resolve method 'field1' in 'T'
Hope someone can help me~
Thanks!
Solution:
Based on @Lukas' answer, I tried several times and found the following points must be done:
In the select
method, all fields must have a type, except those calculated, where adding a type will throw field not found in field list
error.
To add a type to a field, you have to use DSL.field(fieldname, type)
method instead of DSL.field(fieldname).cast(type)
. The latter will throw field not found in field list
error.
In collect
method's collector
object, when getting each field of a record, they must have a type as well. Like
record -> record.get(DSL.field("fieldname", Float.class)),
The complete query will be something like:
Table<Record2<Long, Integer>> table1 = ...;
Table<Record2<Long, Integer>> table2 = ...;
.
.
.
return DSL.
.select(table1.field("table1_field1", Long.class),
DSL.ifnull(
table1.field("table1_field2", Float.class)
.div(table2.field("table2_field1", Float.class)),
0)
.as("result_table_field1"))
.from(table1)
.join(table2)
.on(table1.field("table1_field1", Long.class)
.eq(table2.field("table2_field2", Long.class)))
.orderBy(DSL.field("result_table_field1"))
.collect(Collectors.toMap(
record -> record.get(table1.field("table1_field1", Long.class)),
record -> record.get(DSL.field("result_table_field1", Float.class)),
(v1, v2) -> { throw new InvalidResultException("Duplicate key: " + v1); },
LinkedHashMap::new
));
Both of these approaches are assuming you're using the jOOQ code generator
fetchMap()
already returns a LinkedHashMap
Check out the fetchMap()
Javadoc. It says:
The resulting map is iteration order preserving.
It's effectively a LinkedHashMap
, though it doesn't guarantee this exact type, so you'd have to downcast at your own risk.
collect()
If you write a query that produces a Record2
type, then you can use a type safe collector like this:
LinkedHashMap<T1, T2> map =
ctx.select(T.COL1, T.COL2)
.from(T)
.orderBy(...)
.collect(Collectors.toMap(
Record2::value1,
Record2::value2,
(v1, v2) -> { throw new InvalidResultException("Duplicate key: " + v1); },
LinkedHashMap::new
));
The reason your attempt didn't compile was:
mergeFunction
argument of toMap()
value1()
and value2()
, instead of field1()
, field2()
, but that only works if you have a type safe Record2
in your result setRecord2
, but Record
instead, then you can work without type safety:LinkedHashMap<T1, T2> map =
ctx.select(...)
.from(T)
.orderBy(...)
.collect(Collectors.toMap(
r -> r.get(T.COL1),
r -> r.get(T.COL2),
(v1, v2) -> { throw new InvalidResultException("Duplicate key: " + v1); },
LinkedHashMap::new
));