mapstruct default 方法覆盖其他参数

本文讲述了在使用 MapStruct 过程中遇到的一个问题,即由于 default 方法匹配了相同的输入输出类型,导致字段被错误覆盖。通过查阅官方文档,了解到 MapStruct 在生成实现类时会使用 default 方法。解决此问题的方法包括为 default 方法添加 @Named 注解或将其移动到其他类并引入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于对 mapstruct 仅会用点皮毛,当时以为碰到了一个诡异的 bug,后面排查发现是由于 default 方法使用不当。

下面还原下场景

@Data
public class User {

    private Long id;

    private String name;

    private String className;

    private int age;

    private Date arriveTime;
}

converter 类似这样

@Mapper
public interface UserConverter {

    @Mapping(target = "className", expression = "java(getClassNameFun(userPO.getClassName()))")
    User to(UserPO userPO);

    default String getClassNameFun(String className) {
        return "光明路小学" + className;
    }
}

后面联调发现名称字段被覆盖了,和班级名称一模一样,然后去检查注解是否写错。后续去检查 mapstruct 生成的实现类发现 setName 也调用了 getClassNameFun 方法,所以导致被覆盖。

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2023-02-28T22:44:23+0800",
    comments = "version: 1.4.2.Final, compiler: javac, environment: Java 1.8.0_211 (Oracle Corporation)"
)
public class UserConverterImpl implements UserConverter {

    @Override
    public User to(UserPO userPO) {
        if ( userPO == null ) {
            return null;
        }

        User user = new User();

        user.setId( userPO.getId() );
        user.setName( getClassNameFun( userPO.getName() ) );
        user.setAge( userPO.getAge() );
        user.setArriveTime( userPO.getArriveTime() );

        user.setClassName( getClassNameFun(userPO.getClassName()) );

        return user;
    }
}

后续查阅 mapstruct 官网 发现,生成实现类的时候,如果有 default methods 会去匹配输入输出的类型,如果相同那么会默认使用这个方法。

在这里插入图片描述

有两种方法可以解决这个问题:
(1)对 default 方法加上 @Named 注解

@Mapper
public interface UserConverter {

    @Mapping(target = "className", source = "className", qualifiedByName = "getClassNameFun")
    User to(UserPO userPO);

    @Named("getClassNameFun")
    default String getClassNameFun(String className) {
        return "光明路小学" + className;
    }
}

(2)将 default 方法移到其他类后引入

@Mapper(uses = {ConverterHelper.class})
public interface UserConverter {

    @Mapping(target = "className", source = "className", qualifiedByName = "getClassNameFun")
    User to(UserPO userPO);

}
@Named("ConverterHelper")
public class ConverterHelper {

    @Named("getClassNameFun")
    public static String getClassNameFun(String className) {
        return "光明路小学" + className;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值