When using the "Pojo" classes created by the Jooq-Codegenerator, they (may) contain multiple constructors (default-constructor, interface-constructor, fields-constructor). For example:
public class ProductLang implements IProductLang {
...
public ProductLang() {}
public ProductLang(IProductLang value) {
this.productId = value.getProductId();
this.langId = value.getLangId();
this.name = value.getName();
this.description = value.getDescription();
}
public ProductLang(
Long productId,
Integer langId,
String name,
String description
) {
this.productId = productId;
this.langId = langId;
this.name = name;
this.description = description;
}
...
When this Pojo is now used with Records.mapping
from RecordMapping-Api (see: https://www.jooq.org/doc/latest/manual/sql-execution/fetching/recordmapper/) within ad-hoc-converters (see: https://www.jooq.org/doc/latest/manual/sql-execution/fetching/ad-hoc-converter/), the Records.mapping
can not find the correct constructor, and shows an error.
Following example:
RecordMapper<Record4<Long, Integer, String, String>, ProductLang> r = Records.mapping(ProductLang::new);
Shows error:
When the other two constructors (default-constructor, interface-constructor) are removed from the Pojo the error goes away, and the correct constructor is resolved.
The same problem is also reproducible when using the Records.mapping
within the convertFrom
function within a jooq-dsl-query.
...
multiset(
selectDistinct(
PRODUCT_LANG.PRODUCTID,
PRODUCT_LANG.LANGID,
PRODUCT_LANG.NAME,
PRODUCT_LANG.DESCRIPTION
)
.from(PRODUCT_LANG)
.where(PRODUCT_LANG.PRODUCTID.eq(PRODUCT.PRODUCTID))
).convertFrom(r -> r.map(Records.mapping(ProductLangDTO::new)))
...
Records.mapping
intended to be used with multiple constructors?
That's just how Java works with overloading (both Records::mapping
and ProductLangDTO::new
being overloaded), type inference, and method references. The whole expression becomes ambiguous to the compiler. It would have been possible to infer much more going back and forth through expression trees, but more sophisticated inference was abandoned in JEP 101 and related work (perhaps it's also simply not possible in this particular case - I don't really recall it).
You can either use a lambda to disambiguate:
r.map(mapping((a, b, c, d) -> new ProductLangDTO(a, b, c, d)))
Or if that's too lame, avoid the overloaded constructor, e.g. like this:
public class ProductLang implements IProductLang {
public static ProductLang copy(IProductLang value) {
return new ProductLang(
value.getProductId(),
value.getLangId(),
value.getName(),
value.getDescription()
);
}
...
There are many other ways to solve this, too, including adding mapping utilities to your DTO (instead of calling Records.mapping()
), etc.