首页 > 解决方案 > 是否可以从列表的特定元素映射到自身?

问题描述

给定以下类:

public class Person {
    private String name;
    private List<Role> roles;

    public String getRoleByType(String type){
        for(Role role : roles){
            if(type.equals(role.getType())){
                return role;
            }
        }

        return null;
    }
}

public interface Role {
    public String getType();
}

public class Driver extends Role {
    private String driverLicenseNr;

    public String getType(){
        return "Driver";
    }
}

public class Professional extends Role {
    private String occupation;

    public String getType(){
        return "Professional";
    }
}

public class DriverDTO {
    private String name;
    private String driverLicenseNr;
}

我想要完成的是将 Person 映射到 DriverDTO。

我正在尝试这样的事情:

@Mapper
public abstract class DriverMapper {
    
    @Mapping(target = ".", expression = "java(driver.getRoleByType(\"Driver\"))")
    public abstract DriverDTO convert(Person person);

    public abstract void driverToDriverDTO(Driver driver, @MappingTarget DriverDTO driverDto);
}

但是注释处理器不能简单地用这个生成代码。引发 nullPointerException。如果我这样做(为了简化而隐藏了一些编程细节):

@Mapper
public abstract class DriverMapper {
    
    @Mapping(target = "driverLicenseNr", expression = "java(driver.getRoleByType(\"Driver\").getDriverLicenseNr())")
    public abstract DriverDTO convert(Person person);
}

它有效,但我想利用自动映射,在这种情况下我不会。似乎target="."仅适用于在源中使用单个对象的简单映射。这是真的还是选择了错误的路径来解决这个问题?

标签: javamapstruct

解决方案


使用表达式时 MapStruct 不进行任何评估并使用生成的代码中的内容。

我建议您执行以下操作:

@Mapper
public abstract class DriverMapper {
    
    public DriverDTO convert(Person person) {
        if (person == null) {
            return null;
        }

        Role role = person.getRoleByType("Driver");

        Driver driver = role instanceof Driver ? (Driver) role : null;

        return convert(person, driver);
    }

    @Mapping(target = ".", source = "driver")
    protected abstract DriverDTO convert(Person person, Driver driver);

}

推荐阅读