【问题标题】:@Accessors(fluent = true) from lombok and mapstruct together来自 lombok 和 mapstruct 的 @Accessors(fluent = true)
【发布时间】:2018-07-21 08:15:59
【问题描述】:

我有一个下游服务,我想将其 bean 映射到我的 bean。但是使用mapstruct似乎有问题。

来自下游服务的 Pojo(我无法更改其定义)

@ToString
@Getter
@Setter
@Accessors(fluent = true)
public class PojoA {
   private String stringA;
   private int integer;
}

我想把它转换成 PojoB

@Setter
@Getter
@ToString
public class PojoB {
    private String stringB;
    private int integer;
}

映射器接口

@Mapper
public interface PojoMapper {

    PojoMapper INSTANCE = Mappers.getMapper(PojoMapper.class);
    @Mapping(source = "stringA", target = "stringB")
    PojoB pojoAToPojoB(PojoA pojoA);
}

这失败了,因为它无法找到 getter 作为 fluent 从 getter 中删除前缀,并且, 我知道 mapstruct 生成映射器接口的实现并使用 bean 规范(即获取和设置前缀)

有办法克服吗?

【问题讨论】:

  • 您需要手动指定映射
  • @DarrenForsythe 请详细说明一下。手动,你的意思是,我必须编写一个方法来来回翻译对象吗?
  • 实际上刚刚发现 Mapstruct 可以处理您的确切示例,mapstruct.org/documentation/stable/reference/html/…
  • 医生说可以,但不能。我有同样的问题,我无法解决它。也需要帮助。

标签: java-8 lombok mapstruct


【解决方案1】:

根据 cmets 中的规定,这可以通过编写自定义 AccessorNamingStrategy 来实现,该 AccessorNamingStrategy 将返回方法名称作为流式访问器。

我编写了一个自定义构建器访问器(也可以应用于您的情况),您可以找到它here

除此之外,还有一个针对 MapStruct 的开放 PR #1373,它增加了对构建器的支持,同时它增加了对流式链式访问器的支持。

您的自定义策略(如 PR 中所提议的)可能如下所示:

public class FluentAccessorNamingStrategy extends DefaultAccessorNamingStrategy {

    @Override
    public boolean isSetterMethod(ExecutableElement method) {
        String methodName = method.getSimpleName().toString();

        return methodName.startsWith( "set" ) && methodName.length() > 3 || isBuilderSetter( method );
    }

    protected boolean isBuilderSetter(ExecutableElement method) {
        return method.getParameters().size() == 1 &&
            !JAVA_JAVAX_PACKAGE.matcher( method.getEnclosingElement().asType().toString() ).matches() &&
            method.getReturnType().toString().equals( method.getEnclosingElement().asType().toString() );
    }

    @Override
    public String getPropertyName(ExecutableElement getterOrSetterMethod) {
        String methodName = getterOrSetterMethod.getSimpleName().toString();
        if ( methodName.startsWith( "is" ) || methodName.startsWith( "get" ) || methodName.startsWith( "set" ) ) {
            return Introspector.decapitalize( methodName.substring( methodName.startsWith( "is" ) ? 2 : 3 ) );
        }
        else if ( isBuilderSetter( getterOrSetterMethod ) ) {
            return methodName;
        }
        return Introspector.decapitalize( methodName.substring( methodName.startsWith( "is" ) ? 2 : 3 ) );
    }
}

注意:这适用于流利的 setter,您需要做一些额外的事情才能使其适用于流利的 getter。基于返回类型的meethod.getEnclosingElement(),您需要获取Accessors 注释检查属性并返回方法名称,否则您需要使用默认值。

免责声明:我是 MapStruct 团队的成员之一

【讨论】:

  • 我没有时间来实现这一点,因为我陷入了另一个问题 (stackoverflow.com/questions/48753526/…),现在我正在重新考虑是否应该使用 mapstruct,因为它给了我一个与 Lombok 相处很艰难,如果这件事有效,我一定会检查并标记为正确。
  • MapStruct 适用于 Lombok,您需要检查您的设置是否正确。如果您使用的是annotationProcessorPaths,那么您需要在其中同时指定 MapStruct 和 Lombok。确保您使用的是最新版本的两个框架和最新的 maven-compiler-plugin
猜你喜欢
  • 2020-02-07
  • 1970-01-01
  • 1970-01-01
  • 2018-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-22
  • 2020-03-14
相关资源
最近更新 更多