MapStruct和Lombok一起编译时报错:结果类型中存在未知属性。

184
使用的技术栈: Java 8 MapStruct: 1.2.0.Final Lombok: 1.16.18 IDE: IntelliJ - 已安装Lombok插件 最初,当我删除了getter和setter并添加@Getter和@Setter注解时,遇到了问题。MapStruct无法找到属性,并显示:在结果类型com.vg.once.dto.OneDto中未知属性"id"。你是不是想说"null"? 我了解到,Lombok 1.16.14或更新版本与MapStruct 1.2.0.Beta1或更新版本兼容,并且可以一起使用,但我的版本比所需版本还要新,问题仍然存在。 我已经尝试过另一种解决方案,即运行Lombok的Delombok插件,但问题仍然存在。 以下是项目文件: 实体对象:One.java:
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class One {

    private int id;
    private Integer version;
    private int projectId;
    private String title;
    private String code;
    private int sortOrder;

}
DTO对象:OneDTO.java:
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class OneDto {

    private int id;
    private Integer version;
    private int projectId;
    private String title;
    private String code;
    private int sortOrder;

}
映射器类:OneMapper.java
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import com.vg.once.dto.OneDto;
import com.vg.once.entity.One;

@Mapper
public interface OneMapper {

    @Mapping(target="id", source="one.id")
    OneDto createOne (One one);

}

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.vg</groupId>
  <artifactId>mapstruct</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>Mapstruct-test</name>

    <properties>
        <java.version>1.8</java.version>
        <org.mapstruct.version>1.2.0.Final</org.mapstruct.version>
        <org.projectlombok.version>1.16.18</org.projectlombok.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${org.projectlombok.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-jdk8</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins> 
         <plugin>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok-maven-plugin</artifactId>
                <version>1.16.18.1</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>delombok</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <sourceDirectory>src/main/java</sourceDirectory>
                    <addOutputDirectory>false</addOutputDirectory>
                    <outputDirectory>${project.build.directory}/delombok</outputDirectory>
                    <encoding>UTF-8</encoding>
                    <skip>false</skip>
                    <verbose>false</verbose>
                </configuration>
            </plugin>       
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>  
</project>

构建追踪:

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Mapstruct-test 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- lombok-maven-plugin:1.16.18.1:delombok (default) @ mapstruct ---
[INFO] Delombok complete.
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mapstruct ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.6.1:compile (default-compile) @ mapstruct ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 5 source files to /home/vivekgupta/Documents/workspaces/mapstruct-test/mapstruct/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
[ERROR] /home/vivekgupta/Documents/workspaces/mapstruct-test/mapstruct/src/main/java/com/vg/once/mapper/OneMapper.java:[12,9] Unknown property "id" in result type com.vg.once.dto.OneDto. Did you mean "null"?
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.637 s
[INFO] Finished at: 2017-12-06T19:23:53+05:30
[INFO] Final Memory: 19M/235M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.1:compile (default-compile) on project mapstruct: Compilation failure
[ERROR] /home/vivekgupta/Documents/workspaces/mapstruct-test/mapstruct/src/main/java/com/vg/once/mapper/OneMapper.java:[12,9] Unknown property "id" in result type com.vg.once.dto.OneDto. Did you mean "null"?
[ERROR] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
请告诉我如何同时使用Lombok和MapStruct使其正常工作?
22个回答

299

不起作用的原因是因为 Maven 只使用了 MapStruct 处理器而没有使用 Lombok 的那个。 annotationProcessorPaths 会告诉 Maven 应该使用哪些处理器。

Delombok 不起作用,因为每个类最终都会产生两个文件,我认为 Maven 编译器无法看到它们。

你有2个选项:

选项1:在 annotationProcessorPaths 中添加 lombok 依赖。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.6.1</version>
    <configuration>
        <source>${java.version}</source>
        <target>${java.version}</target>
        <annotationProcessorPaths>
            <path>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${org.projectlombok.version}</version>
            </path>
            <!-- This is needed when using Lombok 1.18.16 and above -->
            <path>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok-mapstruct-binding</artifactId>
                <version>0.2.0</version>
            </path>
            <!-- Mapstruct should follow the lombok path(s) -->
            <path>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct-processor</artifactId>
                <version>${org.mapstruct.version}</version>
            </path>
        </annotationProcessorPaths>
    </configuration>
</plugin>

选项2:

mapstruct-processor依赖项添加到您的依赖项中,并删除annotationProcessorPaths。这样,Maven编译器将会捕获您依赖项中的所有注释处理器。

我建议使用选项1,因为通过选项1,您可以确信在代码中没有使用某些MapStruct传递依赖项和内部类。

编辑:

为确保IntelliJ注释处理也能正常工作,您需要将mapstruct-processor作为provided依赖项添加,由于IDEA-150621。目前,IntelliJ不使用来自Maven的annotationProcessorPaths正确配置项目。

编辑2:

添加有关Lombok 1.18.16所需的lombok-mapstruct-binding信息和注释。


12
我认为“lombok”应该排在“mapstruct-processor”之前。 - Don Srinath
14
顺序不应该有所差别。我们正在与 Lombok 团队共同努力实现这一点。 - Filip
6
我认为这些信息明确需要添加到MapStruct的常见问题中。他们的示例项目可以在Maven构建部分未定义注解处理器的情况下正常工作,但我认为他们应该在那里提到它(我花了一些时间在这里找到解决方案)。 - thunderhook
6
谢谢您对于 lombok-mapstruct-binding 的评论(https://mapstruct.org/faq/#Can-I-use-MapStruct-together-with-Project-Lombok)。可用版本:[0.2.0](https://mvnrepository.com/artifact/org.projectlombok/lombok-mapstruct-binding/0.2.0)。 只需要更改一件事情:<!-- This is needed when using Lombok 1.8.16 and above --> => <!-- This is needed when using Lombok 1.18.16 and above --> - Nemolovich
7
在Mapstruct处理器之前添加Lombok对我也起了作用。 @DonSrinath - w32-mydoom
显示剩余12条评论

39

如果有人正在寻找如何使用Gradle进行配置的方法,请参考以下内容:

dependencies {

   // Lombok
   compileOnly 'org.projectlombok:lombok:1.18.2'
   annotationProcessor 'org.projectlombok:lombok:1.18.2'

   // MapStruct
   compileOnly 'org.mapstruct:mapstruct-jdk8:1.2.0.Final'
   annotationProcessor 'org.mapstruct:mapstruct-processor:1.2.0.Final'

}

3
没有 lombok-mapstruct-binding,这将不再起作用。 - Piotr Żak
@PiotrŻak 这样怎么样? - august0490
如果您正在使用Lombok 1.18.16或更高版本,则还需要添加lombok-mapstruct-binding,以使Lombok和MapStruct配合使用。https://mapstruct.org/faq/ - Piotr Żak

26

在我的Spring Boot Maven项目中,经过多次尝试,最终以下内容起作用:

pom.xml的配置:

  1. properties部分:
    <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.target>11</maven.compiler.target>
            <maven.compiler.source>11</maven.compiler.source>
            <version.lombok>1.18.18</version.lombok>
            <version.mapstruct>1.4.2.Final</version.mapstruct>
            <version.mapstruct-lombok>0.2.0</version.mapstruct-lombok>
        </properties>
  1. 依赖项部分:
    <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${version.lombok}</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${version.mapstruct}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok-mapstruct-binding</artifactId>
            <version>${version.mapstruct-lombok}</version>
        </dependency>
  1. 构建插件部分:
    <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.5.1</version>
                    <configuration>
                        <source>9</source>
                        <target>9</target>
                        <annotationProcessorPaths>
                            <path>
                                <groupId>org.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>${version.mapstruct}</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>${version.lombok}</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok-mapstruct-binding</artifactId>
                                <version>${version.mapstruct-lombok}</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
            </plugins>
        </build>

希望这可以帮到您,之前我的映射器没有映射字段值,但现在这些是源和目标之间的映射器+每个嵌套元素列表也随着字段值一起被映射。


1
仍然适用于2021年12月,谢谢。 - Ilyas Saitov

22

对我来说解决方案真的很简单。

处理器的顺序非常重要。

在我的情况下,mapstruct处理器先于lombok处理器定义。如果顺序不正确,则mapstruct不会生成映射,而只会创建结果类的实例(我在生成的实现中看到了这一点)。

我的插件配置是正确顺序:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>${maven.compiler.plugin.version}</version>
    <configuration>
        <source>15</source>
        <target>15</target>
        <compilerArgs>--enable-preview</compilerArgs>
        <annotationProcessorPaths>
            <path>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </path>
            <path>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct-processor</artifactId>
                <version>${mapstruct.version}</version>
            </path>
        </annotationProcessorPaths>
    </configuration>
</plugin>

当然,您需要添加依赖项:

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${mapstruct.version}</version>
    </dependency>
</dependencies>

嗨,我按照那个顺序得到了这些路径,但是它没有帮助。 - denu
@denu,同意,我不认为顺序有关紧要,这不是一个有帮助的回答。 - undefined

7

我曾经遇到过类似的问题。原来是我的MapStruct版本已经过时了!

我使用的MapStruct版本是1.1.0.Final,但是如果需要Lombok支持,则至少需要1.2.0.Final版本


6

6
我觉得在pom.xml中声明版本的正确方式是引用类似this这样的东西来代替手动指定每个版本。例如,maven-compiler-plugin.versionlombok.version已经在那里了。 属性块 -
<properties>
  <java.version>17</java.version>
  <mapstruct.version>1.5.5.Final</mapstruct.version>
  <lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
</properties>

依赖项块 -

<dependencies>
  <!-- ... -->

  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
  </dependency>

  <dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>${mapstruct.version}</version>
  </dependency>
</dependencies>
建筑模块 -
<build>
  <plugins>
  <!-- ... -->

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>${maven-compiler-plugin.version}</version>
      <configuration>
        <source>${java.version}</source>
        <target>${java.version}</target>
        <annotationProcessorPaths>
          <path>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
          </path>

          <path>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok-mapstruct-binding</artifactId>
            <version>${lombok-mapstruct-binding.version}</version>
          </path>

          <path>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${mapstruct.version}</version>
          </path>
        </annotationProcessorPaths>
      </configuration>
    </plugin>
  </plugins>
</build>

谢谢。对我来说,只需使用以下代码就可以工作: ` org.projectlombok lombok ${lombok.version} ` - Sunny Jha

4

如果在升级Intellij到2020.3版本后出现问题,以下解决方案对我有用。使用Lombok版本:1.18.16,lombok-mapstruct-binding版本:0.2.0。

<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
            <scope>provided</scope>
</dependency>
<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok-mapstruct-binding</artifactId>
            <version>0.2.0</version>
</dependency>

在插件的注解处理部分中,更改lombok和mapstruct插件路径的顺序:

<plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${org.projectlombok.version}</version>
                        </path>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>

                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>

3

显然,这是在Gradle中加载多个注解处理器的正确方法

dependencies {
    implementation "org.mapstruct:mapstruct:1.4.2.Final", "org.projectlombok:lombok:1.18.20"
    annotationProcessor "org.mapstruct:mapstruct-processor:1.4.2.Final", "org.projectlombok:lombok:1.18.20", "org.projectlombok:lombok-mapstruct-binding:0.2.0"
}

2
地图结构只是返回了一个空实例。最近,我将Intellij版本升级到2020.3和Spring Boot 2.4.0,并陷入了这种情况。 当我将Spring版本更改为2.3.o.RELEASE后,在编译后我可以看到地图结构正在正确构建映射。 通过查阅最近更新的地图结构帖子..但需要时间.. :) 所以,现在,我从Maven转移到Gradle项目,一切都非常正常..听起来很奇怪,但是事实如此... 如果有人能发布正确的问题以及解决方案,我会非常感激。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,