当前位置: 首页 > 知识库问答 >
问题:

Mapstruct不使用Lombok定义的生成器

池照
2023-03-14

解决方案:

我不得不更改我的mapstructlombokannotationProcessorPaths的顺序。

我必须将mapstruct放在lombok之上,然后它就起作用了。

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

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

原始问题:

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

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

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

  • 龙目岛 1.18.12
  • 映射结构 1.3.1
  • 爪哇 11
  • 梅文

我找到了Lombok留档,解释了如何将注释处理器添加到maven-pluginhttps://projectlombok.org/setup/maven

但是在执行时,我仍然得到< code >错误:(16,25) java: ClassX没有可访问的无参数构造函数。

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

在至少一个帖子中提到,当将项目拆分为模块时,它是有效的。这对我也有效。当我将DTO移动到另一个maven模块时,在那里构建它们并设置它工作的依赖关系,但这绝对不是我想要的项目结构。另外,由于我可能还需要将我的实体移出,并且我不想为我正在创建的每个Pojo结构创建一个新模块。

我还发现龙目岛边缘版本上的帖子:https://projectlombok.org/download-edge 更改列表中的第二点是

突破性的变化:mapstruct用户现在应该向lombok-mapstruct-绑定添加一个依赖项。这解决了使用lombok(和mapstruct)编译模块的问题。

所以我也尝试了一下。我将存储库添加到我的pom中,添加了龙目岛地图结构绑定并将龙目岛版本设置为边缘快照

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

在此期间,我也将DTO更改为使用@Data,但我想将其更改回来。

最后,这里是代码的一些示例和详细信息。

按单设计服务

@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>

共有1个答案

谢叶五
2023-03-14

使用龙目岛(1.18.18)和地图结构(1.4.2.Final),一切都在我之后工作:

    < li >添加了插件< code > lombok-map struct-binding < li >将lombok-mapstruct-binding添加到插件< code > maven-compiler-plugin 的< code > annotationProcessorPaths 部分

链接:

  • github示例pom.xml:https://github.com/mapstruct/mapstruct-examples/blob/master/mapstruct-lombok/pom.xml
  • 来自https://mapstruct.org/faq/:如果您使用的是Lombok 1.18.16或更高版本,您还需要添加Lombok-mapstruct-绑定以使Lombok和Mapstruct协同工作。
 类似资料:
  • 有没有办法为自定义生成的代码? 考虑以下简单类: 我希望Lombok为生成Setter,就像我在上面的示例中实现的那样。这应该只在用注释的类和作为的属性上完成。其他属性的Setter,在本例中应该像往常一样生成。 是否有办法根据这些标准定制Setter代码的生成?

  • MapStruct知道源状态检查,并且默认情况下使用状态检查器方法(如果存在的话)来验证目标对象中的字段是否应该使用源对象中的值更新。没有状态检查器,MapStruct默认只更新非空值的字段。 我想在REST控制器中使用DTO来使用MapStruct的source presence checknig实现部分更新策略,但是由于我使用Lombok来生成getter和setter,所以我还想生成sour

  • 如何在Map结构中完全禁用使用“构建器”?我根本不想使用它们,因为它们会给我带来各种各样的问题。 我在META-INF下创建了服务文件(我更喜欢一种将其分配给映射构建器=的方法,但我没有看到任何如何在代码中正确执行此操作的示例)。 它仍在尝试使用我想映射到的“ModifiableXXX”实例的不可变“构建器”实例。如果可用,我什至采取一种方法将其强制为可修改类型。 在另一个映射中,使用更新Modi

  • null 这是我运行单元测试时得到的跟踪: 我认为在我的pom.xml文件的build/plugin部分缺少或放错了地方 可以在这里查看项目的源代码: https://github.com/alfredux79/mapstruct-lombock-springboot/tree/stack-overflow-question

  • For方法是在此处生成的,在某些设置器中缺少调用 一些小贴士如何解决这个问题?多谢.