如何在MapStruct中无需绑定源属性生成目标属性值?
MapStruct设置无依赖源属性的Instant字段解决方案
方案一:通过自定义Provider组件+qualifiedByName实现
先定义一个封装当前Instant获取逻辑的Spring组件:
@Component public class InstantProvider { @Named("currentInstant") public Instant getCurrentInstant() { return Instant.now(); } }
在MapStruct Mapper中,通过source = ""声明不依赖源对象的任何属性,再用qualifiedByName关联到Provider的方法:
@Mapper(componentModel = "spring", uses = InstantProvider.class) public interface SourceToTargetMapper { @Mapping(target = "createdAt", source = "", qualifiedByName = "currentInstant") TargetJpa sourceToTarget(Source source); }
该方式将获取当前Instant的逻辑统一封装,所有需要的Mapper都能复用这个组件,完全无需绑定多余的源属性。
方案二:通过@AfterMapping+通用接口复用逻辑
如果多个目标类都需要设置createdAt字段,先定义一个标记接口:
public interface HasCreatedAt { void setCreatedAt(Instant createdAt); }
让TargetJpa实现这个接口:
public class TargetJpa implements HasCreatedAt { // 其他字段 private Instant createdAt; @Override public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } // 对应getter方法 }
创建包含通用设置逻辑的基础Mapper接口:
public interface BaseTimestampMapper { @AfterMapping default void populateCreatedAt(@MappingTarget HasCreatedAt target) { target.setCreatedAt(Instant.now()); } }
最后让业务Mapper继承该基础接口:
@Mapper(componentModel = "spring") public interface SourceToTargetMapper extends BaseTimestampMapper { TargetJpa sourceToTarget(Source source); }
MapStruct会在完成基础转换后自动调用populateCreatedAt方法设置字段,既不依赖源属性,又能在多个Mapper间复用逻辑。
这两种方案都避开了在expression中编写字符串形式的Java代码,也无需引入虚拟源属性,完全匹配你的需求。
内容的提问来源于stack exchange,提问作者Kalec
相关产品推荐
相关产品推荐

