MapStruct为何不使用带泛型的Lombok Builder?
解决MapStruct调用PagedResponse包私有构造器的问题(改用Builder实例化)
这个需求完全可行,核心是让MapStruct使用Lombok生成的Builder来创建PagedResponse实例,而非默认调用构造器。下面是两种可靠的实现方式:
方法一:通过MapStruct注解指定使用Builder
在映射器接口中,给Page<Comment>到PagedResponse<CommentResponse>的映射方法添加@BeanMapping(builder = @Builder)注解,明确告诉MapStruct使用目标类的Builder构建实例:
@Mapper(componentModel = "spring") public interface CommentMapper { // 基础映射:Comment -> CommentResponse CommentResponse toCommentResponse(Comment comment); // 分页映射:Page<Comment> -> PagedResponse<CommentResponse> @Mapping(source = "content", target = "content") @Mapping(source = "number", target = "pageNumber") // 按PagedResponse字段名调整映射关系 @Mapping(source = "size", target = "pageSize") @Mapping(source = "totalElements", target = "totalElements") @Mapping(source = "totalPages", target = "totalPages") @BeanMapping(builder = @Builder) // 关键注解:强制使用Builder实例化 PagedResponse<CommentResponse> toPagedResponse(Page<Comment> page); }
说明:
@BeanMapping(builder = @Builder)会覆盖MapStruct默认的构造器实例化逻辑,转而调用PagedResponse的builder()方法。- 需根据PagedResponse的实际字段名,手动映射Spring Data Page的对应属性(比如Page的
number对应PagedResponse的pageNumber,按需调整)。 - Lombok的
@Builder默认生成公开的builder()方法,跨包也能正常访问,彻底规避包私有构造器的编译问题。
方法二:手动编写默认方法控制Builder调用
如果MapStruct的自动映射不符合预期,可在映射器中编写默认方法,完全手动处理分页转换逻辑,直接调用Builder:
@Mapper(componentModel = "spring") public interface CommentMapper { CommentResponse toCommentResponse(Comment comment); default PagedResponse<CommentResponse> toPagedResponse(Page<Comment> page) { // 先映射分页内容列表 List<CommentResponse> responseContent = page.getContent() .stream() .map(this::toCommentResponse) .collect(Collectors.toList()); // 直接调用泛型Builder构建PagedResponse return PagedResponse.<CommentResponse>builder() .content(responseContent) .pageNumber(page.getNumber()) .pageSize(page.getSize()) .totalElements(page.getTotalElements()) .totalPages(page.getTotalPages()) // 按需添加PagedResponse的其他字段 .build(); } }
说明:
- 这种方式完全由开发者控制映射逻辑,避免MapStruct自动生成错误代码。
- 复用已有的
Comment到CommentResponse的映射方法,保证代码一致性。
补充:错误原因说明
Lombok的@Value注解默认生成包私有的全参构造器,当MapStruct生成的映射器类与PagedResponse不在同一个包时,无法访问该构造器,从而触发编译错误。而@Builder生成的builder()方法是公开的,因此通过Builder实例化是合法的。
内容的提问来源于stack exchange,提问作者Davb
相关产品推荐
相关产品推荐

