【问题标题】:Mapstruct does not use builders defined by LombokMapstruct 不使用 Lombok 定义的构建器
【发布时间】:2020-10-04 00:44:47
【问题描述】:

解决方案:

我不得不更改我的mapstructlombok annotationProcessorPaths 的顺序。

我必须将mapstruct 放在lombok 上方,然后它才起作用。

我将下面的 pom 更新为工作版本,所以这里没有非工作代码。

我还将 lombok 版本转换回当前版本,而不是使用边缘版本。


原问题:

我有 2 组或多或少相同的类(参见下面的示例)

  • 一组是我的 API 的 DTO,我希望使用 Lombok 的 @Value 和 @Builder 使其不可变
  • 一组是要存储在数据库中的实体。使用 Lombok 的 @Data

最初我将项目设置为使用:

  • 龙目岛 1.18.12
  • Mapstruct 1.3.1
  • Java 11
  • 马文

我发现 Lombok 文档解释了如何将注释处理器添加到 maven-plugin https://projectlombok.org/setup/maven

但是在执行时我仍然得到Error:(16,25) java: ClassX does not have an accessible parameterless constructor.

搜索此消息时,我发现了一些 2 到 3 年的问题,但没有任何最新信息。我还看到,这些帖子的问题已解决。

在将项目拆分为模块时,至少在其中一篇文章中提到了它的工作原理。这也对我有用。当我将 DTO 移动到另一个 maven 模块时,在那里构建它们并设置它工作的依赖项,但这绝对不是我想要的项目结构。此外,因为我可能还需要将我的实体移出,并且我不想为我正在创建的每个 Pojo 结构创建一个新模块。

我还在 Lombok Edge 版本上找到了该帖子: https://projectlombok.org/download-edge 更改列表中的第二点是

重大更改:mapstruct 用户现在应该向 lombok-mapstruct-binding 添加依赖项。这解决了使用 lombok(和 mapstruct)编译模块的问题。

所以我也试过了。 我将存储库添加到我的 pom 中,添加了 lombok-mapstruct-binding 并将 lombok 版本设置为 edge-SNAPSHOT

但即使在清理之后编译步骤也会失败。


在这期间,我也更改了我的 DTO 以使用 @Data,但我想将它改回来。

最后是代码的一些例子和细节。

DTO

@Data
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = BDto.class, name = "b"),
        @JsonSubTypes.Type(value = CDto.class, name = "c")
})
public abstract class ADto {
    private long id;
    private String type;
    private Set<String> metadata;
    private Set<String> tags;
}

@Data
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BDto extends ADto {
    private String path;

    @Builder
    private BDto(long id, String path, Set<String> metadata, Set<String> tags) {
        super(id, "b", metadata, tags);
        this.path = path;
    }
}

@Data
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class CDto extends ADto {
    private String name;
    private Set<A> collection;

    @Builder
    private CDto(long id, String name, Set<A> collection, Set<String> metadata, Set<String> tags) {
        super(id, "c", metadata, tags);
        this.collection = collection;
        this.name = name;
    }
}

实体

@Entity
@Table
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type")
@AllArgsConstructor
@NoArgsConstructor
@Getter
public abstract class A extends PanacheEntityBase {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected long id;

    @Column(name = "type", insertable = false, updatable = false)
    private String type;

    /* ... */
}

@Entity
@DiscriminatorValue("b")
@NoArgsConstructor
@Getter
@ToString
public class B extends A {
    public B(long id, String path, Set<String> metadata, Set<Tag> tags) {
        super(id, "b", metadata, tags);
        this.path = path;
    }

    public B(String path) {
        super(0, "b", new HashSet<>(), new HashSet<>());
        this.path = path;
    }

    @Column(name = "path")
    @Setter
    private String path;
}

@Entity
@DiscriminatorValue("c")
@NoArgsConstructor
@Getter
public class C extends A {
    public C(long id, String name, List<A> collection, Set<String> metadata, Set<Tag> tags) {
        super(id, "c", metadata, tags);
        this.collection = collection;
        this.name = name;
    }

    @Column(name = "name")
    private String name;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "c_id")
    @OrderBy("order")
    List<A> collection;
}

映射器

public interface AMapper {
    default String tagToDto(Tag tag) {
        return tag.getTag();
    }

    default Tag tagFromDto(String tag) {
        return Tag.createIfNotExists(tag);
    }
}

@Mapper()
public interface BMapper extends AMapper {
    @Override
    @Mapping(target = "tags",
            qualifiedByName = "tagToDto")
    BDto toDto(B b);

    @Override
    @Mapping(target = "tags",
            qualifiedByName = "tagToEntity")
    B toEntity(BDto b);
}

@Mapper()
public interface CMapper extends AMapper {
    @Override
    @Mapping(target = "tags",
            qualifiedByName = "tagToDto")
    CDto toDto(C b);

    @Override
    @Mapping(target = "tags",
            qualifiedByName = "tagToEntity")
    C toEntity(CDto b);
}

波姆

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <artifactId>dummy</artifactId>
    <groupId>dummy</groupId>
    <version>0.1.0</version>
    <packaging>pom</packaging>

    <properties>
        <compiler-plugin.version>3.8.1</compiler-plugin.version>
        <maven.compiler.parameters>true</maven.compiler.parameters>

        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        <lombok.version>1.18.12</lombok.version>
        <mapstruct.version>1.3.1.Final</mapstruct.version>
    </properties>

    <repositories>
        <repository>
            <id>projectlombok.org</id>
            <url>https://projectlombok.org/edge-releases</url>
        </repository>
    </repositories>

    <dependencies>
        <!-- other stuff -->

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

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${compiler-plugin.version}</version>
                <configuration>
                    <annotationProcessorPaths>
                        <annotationProcessorPath>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${mapstruct.version}</version>
                        </annotationProcessorPath>
                        <annotationProcessorPath>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </annotationProcessorPath>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

【问题讨论】:

  • lombok-mapstruct-binding 也应该在annotationProcessorPaths 中。
  • @Filip 我更新了上面的代码。我按照您的建议将lombok-mapstruct-binding 添加到annotationProcessorPaths,但遗憾的是我仍然遇到同样的错误。也许还有一个问题:我真的必须使用 lombok 的边缘版本,还是应该使用 1.18.12 版本?
  • 它也应该适用于 1.18.12。
  • @Filip 我找到了一个解决方案,这让我有点困惑。当更改 lombok 和 mapstruct annotationProcessorPaths 的顺序时,它可以工作。因此,mapstruct 在列表中排在第一位,在 lombok 排在第二位。然后,我还使用edge-SNAPSHOT 版本对其进行了测试,lombok-mapstruct-binding 的顺序没有改变任何东西,但 lombok 必须在 mapstruct 之后才能工作。我在事故中测试的最后一件事是将订单切换回来而不是清除(mvn clear)并且编译工作。所以我猜目标文件夹中的构建类有一些东西。
  • 是的,您也可以在这里查看接受的答案stackoverflow.com/questions/65955000/… 它也是官方mapstruct 文档mapstruct.org/documentation/stable/reference/html/#_set_up

标签: maven lombok java-11 mapstruct


【解决方案1】:

使用 lombok (1.18.18) 和 mapstruct (1.4.2.Final) 在我之后一切正常:

  1. 添加插件lombok-mapstruct-binding
  2. 将 lombok-mapstruct-binding 添加到插件 maven-compiler-pluginannotationProcessorPaths 部分

链接:

【讨论】:

    猜你喜欢
    • 2021-07-20
    • 2020-03-14
    • 1970-01-01
    • 2018-11-01
    • 2023-03-29
    • 2020-02-07
    • 1970-01-01
    • 1970-01-01
    • 2021-05-03
    相关资源
    最近更新 更多