MapStruct映射器内调用其他映射器及方法跨映射复用问题
解决方案
场景回顾
源DTO
AuditClass{ protected ZonedDateTime creationDateTime; protected ZonedDateTime lastUpdateDateTime; } LocationRequest extends AuditClass{ //some fields }
目标DTO
CachedLocation{ //some fields protected LocalDateTime updateTime; }
当前映射器代码
@Mapper(componentModel = "spring", uses = {LocalAndZonedDateTimeMapper.class}) public interface LocationRequestResponseMapper{ @Mapping(source = ".", target = "updateTime", qualifiedByName = "getUpdateTime") CachedLocation toCachedLocation(LocationRequest location); //问题2:我希望将该方法迁移至另一个映射器,以便在所有请求映射中复用,是否有可行方案? @Named("getUpdateTime") default LocalDateTime getUpdateTime(AuditClass request) { //问题1:我希望在此方法中使用LocalAndZonedDateTimeMapper,但当前映射器是接口,无法使用抽象类,该如何实现? if (request.getCreationDateTime() != null) { return localAndZonedDateTimeMapper.toLocalDateTime(request.getCreationDateTime()); } else if (request.getLastUpdateDateTime() != null) { return localAndZonedDateTimeMapper.toLocalDateTime(request.getLastUpdateDateTime()); } return null; } }
问题1解决方案:在接口default方法中使用LocalAndZonedDateTimeMapper
因为映射器使用了spring组件模型,可通过在接口中添加一个抽象方法并标记@Autowired来获取LocalAndZonedDateTimeMapper实例,然后在default方法中调用该方法使用:
@Mapper(componentModel = "spring", uses = {LocalAndZonedDateTimeMapper.class}) public interface LocationRequestResponseMapper{ @Mapping(source = ".", target = "updateTime", qualifiedByName = "getUpdateTime") CachedLocation toCachedLocation(LocationRequest location); // 声明抽象方法,由Spring自动注入mapper实例 @Autowired LocalAndZonedDateTimeMapper getLocalAndZonedDateTimeMapper(); @Named("getUpdateTime") default LocalDateTime getUpdateTime(AuditClass request) { LocalAndZonedDateTimeMapper mapper = getLocalAndZonedDateTimeMapper(); if (request.getCreationDateTime() != null) { return mapper.toLocalDateTime(request.getCreationDateTime()); } else if (request.getLastUpdateDateTime() != null) { return mapper.toLocalDateTime(request.getLastUpdateDateTime()); } return null; } }
MapStruct生成的Spring实现类会自动处理这个抽象方法的注入,无需额外配置。
问题2解决方案:独立复用类实现全局方法复用
由于无法将方法移入LocalAndZonedDateTimeMapper(循环依赖),可以创建一个独立的审计时间处理映射器,将getUpdateTime方法迁移至此,其他需要该逻辑的映射器通过uses属性引入即可:
1. 创建独立的AuditTimeMapper
@Mapper(componentModel = "spring", uses = {LocalAndZonedDateTimeMapper.class}) public interface AuditTimeMapper { @Autowired LocalAndZonedDateTimeMapper getLocalAndZonedDateTimeMapper(); @Named("getUpdateTime") default LocalDateTime getUpdateTime(AuditClass request) { LocalAndZonedDateTimeMapper mapper = getLocalAndZonedDateTimeMapper(); if (request.getCreationDateTime() != null) { return mapper.toLocalDateTime(request.getCreationDateTime()); } else if (request.getLastUpdateDateTime() != null) { return mapper.toLocalDateTime(request.getLastUpdateDateTime()); } return null; } }
2. 修改原映射器引入AuditTimeMapper
@Mapper(componentModel = "spring", uses = {AuditTimeMapper.class}) public interface LocationRequestResponseMapper{ @Mapping(source = ".", target = "updateTime", qualifiedByName = "getUpdateTime") CachedLocation toCachedLocation(LocationRequest location); }
3. 其他映射器复用方式
任何需要处理AuditClass时间转换的映射器,只需在@Mapper的uses中添加AuditTimeMapper.class,并通过qualifiedByName = "getUpdateTime"指定方法即可,无需重复编写逻辑。
这种方式既避免了循环依赖,又实现了逻辑的全局复用,符合模块化设计原则。
内容的提问来源于stack exchange,提问作者Rahul verma
相关产品推荐
相关产品推荐

