我个人反对用字符串编写 Java 代码。我想要实现的目标是通过表达式 100% 可行。然而,我想尝试找到一种无需这样做的方法。
情况:
TargetJpa {
...
Instant createdAt;
}
我想做的事:
// using 1.5.2.Final
@Mapper(...)
public interface JpaMapper {
@Mapping(target = "createdAt", qualifiedByName = "now")
TargetJpa toJpa(Srouce s);
@Named("now")
default Instant now() {
return Instant.now();
}
}
这显然行不通。它抱怨我缺少来源。这是正确的,我不需要来源,我正在生成一个值。但这不可能是一个常数。我个人希望尽可能少地在字符串中使用 java 代码。
Ofc,有一个明显的解决方法,传递一个虚拟源值。
@Mapper(...)
public interface JpaMapper {
@Mapping(target = "createdAt", source = "s", qualifiedByName = "now")
TargetJpa toJpa(Srouce s);
@Named("now")
default Instant now(Source s) {
return Instant.now();
}
}
但这有一个巨大的缺点。如果我不必命名来源,我可以从这个界面中删除这个“现在”,制作一个“InstantMapper”并重用代码:
@InstantMapper
public class InstantMapperImpl {
@Now
default Instant now() {
return Instant.now();
}
}
然后将其用在任何东西上:
... uses = { ..., InstantMapperImpl.class }
...
@Mapping(target = "createdAt", qualifiedBy = {InstantMapper.class, Now.class})
TargetJpa1 toJpa(Srouce1 s);
@Mapping(target = "createdAt", qualifiedBy = {InstantMapper.class, Now.class})
TargetJpa2 toJpa(Srouce2 s);
@Mapping(target = "createdAt", qualifiedBy = {InstantMapper.class, Now.class})
TargetJpa3 toJpa(Srouce3 s);
有什么方法可以实现这一目标,而不将自己束缚在我根本不需要的某些来源上?
MapStruct 目前不支持使用随机方法映射到特定属性。使用
Mapping#target
时,您可以使用几个选项来作为映射源:
source
- 来自特定来源的地图expression
- 使用表达式进行映射constant
- 使用一些常量值进行映射ignore
- 忽略映射所有其余属性都以一种或另一种方式用于指定映射的其他一些内容。
如果未提供这 4 个选项中的任何一个,则假定
target
中的值是 source
中的值。
例如
@Mapping(target = "createdAt", qualifiedByName = "now")
实际上意味着
@Mapping(target = "createdAt", source = "createdAt", qualifiedByName = "now")
如果您有兴趣在 MapStruct 中看到类似您所请求的内容,我建议您提出 功能请求
如果我正确理解了要求,您可以在这种情况下使用表达式。有点笨重,但应该足够了。
@Mapper(...)
public interface JpaMapper {
@Mapping(target = "createdAt", expression = "java(this.now())")
TargetJpa toJpa(Srouce s);
default Instant now() {
return Instant.now();
}
}