当使用 Jooq-Codegenerator 创建的“Pojo”类时,它们(可能)包含多个构造函数(默认构造函数、接口构造函数、字段构造函数)。例如:
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;
}
...
当此 Pojo 现在与 RecordMapping-Api 中的
Records.mapping
一起使用时(请参阅:https://www.jooq.org/doc/latest/manual/sql-execution/fetching/recordmapper/)转换器(参见:https://www.jooq.org/doc/latest/manual/sql-execution/fetching/ad-hoc-converter/),Records.mapping
找不到正确的构造函数,并显示错误。
以下示例:
RecordMapper<Record4<Long, Integer, String, String>, ProductLang> r = Records.mapping(ProductLang::new);
显示错误:
当其他两个构造函数(默认构造函数、接口构造函数)从 Pojo 中删除时,错误就会消失,并解决正确的构造函数。
在 jooq-dsl-query 中的
Records.mapping
函数中使用 convertFrom
时,也可以重现同样的问题。
...
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
是否可以与多个构造函数一起使用?
这就是 Java 的重载(
Records::mapping
和 ProductLangDTO::new
都重载)、类型推断和方法引用的工作原理。整个表达式对于编译器来说变得不明确。通过表达式树来回推断更多的事情是可能的,但是在 JEP 101 和相关工作中放弃了更复杂的推断(也许在这种特殊情况下也是不可能的 - 我真的不记得了).
您可以使用 lambda 来消除歧义:
r.map(mapping((a, b, c, d) -> new ProductLangDTO(a, b, c, d)))
或者如果这太蹩脚,请避免重载的构造函数,例如像这样:
public class ProductLang implements IProductLang {
public static ProductLang copy(IProductLang value) {
return new ProductLang(
value.getProductId(),
value.getLangId(),
value.getName(),
value.getDescription()
);
}
...
还有许多其他方法可以解决此问题,包括向 DTO 添加映射实用程序(而不是调用
Records.mapping()
)等。