您的位置:首页 > 房产 > 家装 > 高新营销型网站建设公司_怀化网络推广公司_关键词批量调词 软件_挖掘关键词爱站网

高新营销型网站建设公司_怀化网络推广公司_关键词批量调词 软件_挖掘关键词爱站网

2025/1/9 13:53:20 来源:https://blog.csdn.net/weixin_37848710/article/details/144212657  浏览:    关键词:高新营销型网站建设公司_怀化网络推广公司_关键词批量调词 软件_挖掘关键词爱站网
高新营销型网站建设公司_怀化网络推广公司_关键词批量调词 软件_挖掘关键词爱站网

使用 MapStruct 的 @AfterMapping 注解不生效,与Lombok的@Builder冲突

      • 简介
      • 需求场景
      • 问题现象
      • 问题原因
      • 解决方案
      • 代码实现
        • // 方案一代码实现:
        • // 方案二代码实现:

在 Quarkus 框架项目中使用了 MapStruct 的 @AfterMapping 注解不生效,究其原因是在对应实体类中使用了 Lombok 的 @Builder 注解,两者在使用上冲突了。

简介

MapStruct:MapStruct - Java bean mappings, the easy way!

Lombok:Very spicy additions to the Java programming language.

基于projectlombok-version:1.18.30、org.mapstruct.version:1.5.5.Final

需求场景

我的一个POJO转换为一个DTO对象,其中对象一个属性为List<Object>类型,我需要在转换后对该属性值得集合进行排序。故我想到了使用MapStruct@AfterMapping注解, 该注解标注的默认方法能在对象转换时(标记要在生成的映射方法的末尾、映射方法的最后一条语句之前 return 调用的方法。)执行相关的自定义方法逻辑。这里对于我的需求就是返回转换目标之前对其List<Object>属性数据进行排序。

问题现象

我在 Mapper.java 类中编写的被@AfterMapping注解标注的代码/逻辑并没有添加到 @ generated Implementation class 类中。

Mapper.java

@Mapper(componentModel = "cdi")
public interface StatusConverter {@Mappings({@Mapping(target = "orderId", source = "status.orderId"),@Mapping(target = "statusList", source = "statusLogList")})StatusDetail mapTo(OrderStatus status, List<StatusDetail.StatusLog> statusLogList);@AfterMappingdefault void sortStatusList(@MappingTarget StatusDetail statusDetail) {if (Objects.nonNull(statusDetail.getStatusList())) {statusDetail.getStatusList().sort(Comparator.comparing(StatusDetail.StatusLog::getUpdatedAt));}}
}

Generated Implementation class

@Generated(value = "org.mapstruct.ap.MappingProcessor",date = "2024-12-03T14:06:26+0800",comments = "version: 1.5.5.Final, compiler: javac, environment: Java 17.0.11 (Eclipse Adoptium)"
)
@ApplicationScoped
public class StatusConverterImpl implements StatusConverter {@Overridepublic StatusDetail mapTo(OrderStatus status, List<StatusDetail.StatusLog> statusLogList) {if ( status== null && statusLogList== null ) {return null;}StatusDetail.StatusDetailBuilder statusDetail = StatusDetail.builder();if ( status != null ) {statusDetail.orderId( status.getOrderId() );}List<StatusDetail.StatusLog> list = statusLogList;if ( list != null ) {statusDetail.statusList( new ArrayList<StatusDetail.StatusLog>( list ) );}// FIXME: 注意这里并没有调用 @AfterMapping 标注的方法return statusDetail.build();}
}

问题原因

我在StatusDetail实体类中使用了 Lombok 的 @Builder 注解, 由于使用了@Builder注解, MapStruct在编译时, 会用EntityBuilder.build() 完成目标对象的实例化,而非使用new对象后setter的方式实例化对象。在生成的映射方法的末尾、映射方法的最后一条语句 return 之前只能提供StatusDetail.StatusDetailBuilder对象, 而非StatusDetail对象,而@AfterMapping标注的方法参数是需要StatusDetail对象,所以未调用。 实体类代码如下所示:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StatusDetail {private String orderId;private List<StatusLog> statusList;@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic static class StatusLog {private String id;private String orderId;private String sourceStatus;private String targetStatus;private Instant createdAt;private Instant updatedAt;}
}

解决方案

  • @Mapper上禁用对于builder的支持,@builder#disableBuilder
  • @AfterMapping标注方法上@MappingTarget标注参数由Bean改为BeanBuilder对象

代码实现

// 方案一代码实现:
@Mapper(componentModel = "cdi", builder = @Builder(disableBuilder = true))
public interface StatusConverter {@Mappings({@Mapping(target = "orderId", source = "status.orderId"),@Mapping(target = "statusList", source = "statusLogList")})StatusDetail mapTo(OrderStatus status, List<StatusDetail.StatusLog> statusLogList);@AfterMappingdefault void sortStatusList(@MappingTarget StatusDetail statusDetail) {if (Objects.nonNull(statusDetail.getStatusList())) {statusDetail.getStatusList().sort(Comparator.comparing(StatusDetail.StatusLog::getUpdatedAt));}}
}
// @generated impl
@Generated(value = "org.mapstruct.ap.MappingProcessor",date = "2024-12-03T15:23:29+0800",comments = "version: 1.5.5.Final, compiler: javac, environment: Java 17.0.11 (Eclipse Adoptium)"
)
@ApplicationScoped
public class StatusConverterImpl implements StatusConverter {@Overridepublic StatusDetail mapTo(OrderStatus status, List<StatusDetail.StatusLog> statusLogList) {if ( status== null && statusLogList== null ) {return null;}StatusDetail statusDetail = new StatusDetail();if ( status != null ) {statusDetail.setOrderId( status.getOrderId() );}List<StatusDetail.StatusLog> list = statusLogList;if ( list != null ) {statusDetail.setStatusList( new ArrayList<StatusDetail.StatusLog>( list ) );}sortStatusList( statusDetail );return statusDetail;}
}
// 方案二代码实现:
@Mapper(componentModel = "cdi")
public interface StatusConverter {@Mappings({@Mapping(target = "orderId", source = "status.orderId"),@Mapping(target = "statusList", source = "statusLogList")})StatusDetail mapTo(OrderStatus status, List<StatusDetail.StatusLog> statusLogList);@AfterMappingdefault void sortStatusList(@MappingTarget DepositStatusDetail.OrderStatusBuilder statusDetailBuilder, List<OrderStatus.StatusLog> statusList) {if (CollectionUtil.isNotEmpty(statusList)) {statusDetailBuilder.statusList(statusList.stream().sorted(Comparator.comparing(StatusDetail.StatusLog::getUpdatedAt)).toList());}}
}
// @generated impl
@Generated(value = "org.mapstruct.ap.MappingProcessor",date = "2024-12-03T15:15:58+0800",comments = "version: 1.5.5.Final, compiler: javac, environment: Java 17.0.11 (Eclipse Adoptium)"
)
@ApplicationScoped
public class StatusConverterImpl implements StatusConverter {@Overridepublic StatusDetail mapTo(OrderStatus status, List<StatusDetail.StatusLog> statusLogList) {if ( status== null && statusLogList== null ) {return null;}StatusDetail.StatusDetailBuilder statusDetailBuilder = StatusDetail.builder();if ( status != null ) {statusDetail.orderId( status.getOrderId() );}List<StatusDetail.StatusLog> list = statusLogList;if ( list != null ) {statusDetail.statusList( new ArrayList<StatusDetail.StatusLog>( list ) );}sortStatusList( statusDetailBuilder, statusList );return statusDetail.build();}
}

参考:
https://github.com/mapstruct/mapstruct/issues/1556
https://blog.csdn.net/nxhljt/article/details/123893492

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com