将 Mapstruct 升级到 1.4。2.Final

Upgrade Mapstruct to 1.4.2.Final

我正在将项目 mapstruct 依赖项从 1.2.0.Final 升级到 1.4.2.Final。 一切顺利,util 落在一个复杂的映射器上,它看起来像下面的代码片段:

@Mapper(componentModel = "spring")
public abstract class CustomMapper{

@Named("mapTestla")
@Mapping(target = "f", source = "t.f") 
public abstract TestlaDTO mapTestla(Testla t) {}

@Named("mapBar")
@Mapping(target = "t", source = "b.t", qualifiedByName = "mapTestla") 
public abstract BarDTO mapBar(Bar b) {}

@Mappings({@Mapping(target = "a", source = "f.a"), 
@Mapping(target = "b", source = "f.b", qualifiedByName = "mapBar")})
public abstract FooDTO mapFoo(Foo f) {}

}


class Foo {
 String a;
 Bar b;
}

class Bar {
 Tesla t;
}

class Testla {
String f;
}


class FooDTO {
 String a;
 Bar b;
}

class BarDTO {
 TeslaDTO t;
}

class TestlaDTO {
String f;
}

正如您在错误中看到的那样,mapstruct 没有检测到引用的方法,尽管它们被注释为 @Named。看起来像是 spring aop proxy 问题..

知道这个问题吗?

PS: 我不想将映射器分成多个映射器,因为我们 运行 落后于计划,这可能会导致影响.

错误得到:

错误:限定符错误。找不到使用@Named#value: [ mapBar] 注释的方法。有关详细信息,请参阅 https://mapstruct.org/faq/#qualifier

错误:限定符错误。没有找到用@Named#value: [ mapTestla] 注释的方法。有关详细信息,请参阅 https://mapstruct.org/faq/#qualifier

您似乎从不同于 MapStruct 的库中导入了不正确的 @Named 注释。
您的示例在 MapStruct 1.4 中运行良好。2.Final。

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.Named;


@Mapper(componentModel = "spring")
public abstract class CustomMapper{

    @Named("mapTestla")
    @Mapping(target = "f", source = "t.f")
    public abstract TestlaDTO mapTestla(Testla t);

    @Named("mapBar")
    @Mapping(target = "t", source = "b.t", qualifiedByName = "mapTestla")
    public abstract BarDTO mapBar(Bar b);

    @Mappings({@Mapping(target = "a", source = "f.a"),
           @Mapping(target = "b", source = "f.b", qualifiedByName = "mapBar")})
    public abstract FooDTO mapFoo(Foo f) ;
}

生成的代码:

@Component
public class CustomMapperImpl extends CustomMapper {
    @Override
    public TestlaDTO mapTestla(Testla t) {
        if ( t == null ) {
            return null;
        }
        TestlaDTO testlaDTO = new TestlaDTO();
        testlaDTO.f = t.f;
        return testlaDTO;
    }

    @Override
    public BarDTO mapBar(Bar b) {
        if ( b == null ) {
            return null;
        }
        BarDTO barDTO = new BarDTO();
        barDTO.t = mapTestla( b.t );
        return barDTO;
    }

    @Override
    public FooDTO mapFoo(Foo f) {
        if ( f == null ) {
            return null;
        }
        FooDTO fooDTO = new FooDTO();
        fooDTO.a = f.a;
        fooDTO.b = mapBar( f.b );
        return fooDTO;
    }
}

根据文档:Mapping object references
您不需要通过方法限定符显式指定内部对象映射。为所有对象指定映射方法就足够了。 MapStract 将自动对它们进行限定。

@Mapper(componentModel = "spring")
public abstract class CustomMapper {
    public abstract TestlaDTO mapTestla(Testla t);

    public abstract BarDTO mapBar(Bar b);

    public abstract FooDTO mapFoo(Foo f) ;
}

生成的代码:

@Component
public class CustomMapperImpl extends CustomMapper {

    @Override
    public TestlaDTO mapTestla(Testla t) {
        if ( t == null ) {
            return null;
        }
        TestlaDTO testlaDTO = new TestlaDTO();
        testlaDTO.f = t.f;
        return testlaDTO;
    }

    @Override
    public BarDTO mapBar(Bar b) {
        if ( b == null ) {
            return null;
        }
        BarDTO barDTO = new BarDTO();
        barDTO.t = mapTestla( b.t );
        return barDTO;
    }

    @Override
    public FooDTO mapFoo(Foo f) {
        if ( f == null ) {
            return null;
        }
        FooDTO fooDTO = new FooDTO();
        fooDTO.a = f.a;
        fooDTO.b = mapBar( f.b );
        return fooDTO;
    }
}

如您所见,MapStruct 生成了相同的映射器代码,但没有附加注释!