You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mapstruct同配置多目标类映射方案咨询

复用MapStruct映射配置的三种可行方案

针对你遇到的「同结构不同包的自动生成类,无法继承但要复用映射配置」的场景,这三个方案可以直接解决:

方案1:用@MappingConfig抽公共配置(官方推荐)

这是MapStruct专门为复用映射规则设计的特性,把所有公共的@Mapping定义在一个配置接口里,两个Mapper直接引用即可:

步骤1:定义公共映射配置接口

import org.mapstruct.Mapping;
import org.mapstruct.MappingConfig;

@MappingConfig
public interface DittaIndividualeMappingConfig {
    // 把所有共用的映射规则写在这里
    @Mapping(source = "codiceFiscale", target = "taxCode")
    @Mapping(source = "ragioneSociale", target = "companyName")
    @Mapping(source = "dataIscrizione", target = "registrationDate", dateFormat = "yyyy-MM-dd")
    // 其他字段映射...
}

步骤2:在两个Mapper中引用配置

// 第一个Mapper,目标类是package1下的DI
import org.mapstruct.Mapper;
import com.package1.DI;
import com.yourpackage.DittaIndividualeDTO;

@Mapper(config = DittaIndividualeMappingConfig.class)
public interface FirstDIMapper {
    DI toDI(DittaIndividualeDTO source);
}

// 第二个Mapper,目标类是package2下的DI
import org.mapstruct.Mapper;
import com.package2.DI;
import com.yourpackage.DittaIndividualeDTO;

@Mapper(config = DittaIndividualeMappingConfig.class)
public interface SecondDIMapper {
    DI toDI(DittaIndividualeDTO source);
}

MapStruct会自动把配置里的所有映射规则应用到各自的toDI方法上,完全复用配置逻辑。

方案2:泛型抽象类统一映射逻辑

如果需要复用的不仅是字段映射,还有自定义转换逻辑,可以用泛型抽象类来封装,两个Mapper继承后指定具体目标类型:

import org.mapstruct.Mapping;
import org.mapstruct.Mapper;

public abstract class AbstractDIMapper {
    // 公共映射规则
    @Mapping(source = "codiceFiscale", target = "taxCode")
    @Mapping(source = "ragioneSociale", target = "companyName")
    public abstract <T> T toDI(DittaIndividualeDTO source);

    // 如果有自定义转换方法,也可以写在这里复用
    protected String normalizePhone(String phone) {
        return phone != null ? phone.replaceAll("[^0-9]", "") : null;
    }
}

// 第一个Mapper
@Mapper
public interface FirstDIMapper extends AbstractDIMapper {
    @Override
    com.package1.DI toDI(DittaIndividualeDTO source);
}

// 第二个Mapper
@Mapper
public interface SecondDIMapper extends AbstractDIMapper {
    @Override
    com.package2.DI toDI(DittaIndividualeDTO source);
}

这种方式适合需要复用自定义转换逻辑的场景,MapStruct会自动处理泛型的类型擦除问题,只要两个DI类结构一致就没问题。

方案3:抽取公共转换组件(适合Spring环境)

如果你的项目用了Spring,可以把公共的映射逻辑抽到一个Spring组件里,两个Mapper注入这个组件来复用:

步骤1:定义公共转换组件

import org.springframework.stereotype.Component;

@Component
public class DittaIndividualeConverter {
    public void fillDICommonFields(DittaIndividualeDTO source, Object target) {
        // 利用类结构一致的特性,强转后设置公共字段
        if (target instanceof com.package1.DI) {
            com.package1.DI di = (com.package1.DI) target;
            di.setTaxCode(source.getCodiceFiscale());
            di.setCompanyName(source.getRagioneSociale());
        } else if (target instanceof com.package2.DI) {
            com.package2.DI di = (com.package2.DI) target;
            di.setTaxCode(source.getCodiceFiscale());
            di.setCompanyName(source.getRagioneSociale());
        }
        // 其他公共字段设置...
    }
}

步骤2:在Mapper中引用组件

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.springframework.beans.factory.annotation.Autowired;

@Mapper(componentModel = "spring")
public abstract class FirstDIMapper {
    @Autowired
    protected DittaIndividualeConverter converter;

    // 忽略公共字段,交给组件处理
    @Mapping(target = "taxCode", ignore = true)
    @Mapping(target = "companyName", ignore = true)
    protected abstract com.package1.DI toDI(DittaIndividualeDTO source);

    // 用@AfterMapping调用公共组件补全字段
    @AfterMapping
    protected void fillCommonFields(DittaIndividualeDTO source, @MappingTarget com.package1.DI target) {
        converter.fillDICommonFields(source, target);
    }
}

第二个Mapper同理,只需要把目标类换成com.package2.DI即可。


内容的提问来源于stack exchange,提问作者Lore

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 00:00:12