@MAPSTRUCT. 源参数中不存在名为 “packaging” 的属性

huangapple go评论143阅读模式
英文:

@MAPSTRUCT. No property named "packaging" exists in source parameter(s)

问题

I am writing an MVC REST application with Spring Boot and Hibernate. I decided to do DTO mapping using MAPSTRUCT. It seems that I did everything according to the guide, but an error is issued. What is the problem, I cannot understand. There is very little information on forums and on google.

P.S. At first I thought that the problem was in Lombok, so I removed Lombok and manually assigned getters / setters. Then the problem was not solved. I took both in the Drink class and in the DrinkDTO I prescribed getters / setters. It still didn't help.

Drink:

@Entity
@Table(name = "drink", schema = "public")
public class Drink {

    public Drink() { // Constructor for Hibernate

    }

    // Fields
    //
    private @Id
    @GeneratedValue
    Long id;

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

    @Column(name = "price")
    private float price;

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

    @Column(name = "is_deleted")
    private boolean isDeleted;

    // Relationships
    //
    @ManyToOne
    @JoinColumn(name = "packaging_id")
    private Packaging packaging;

    @ManyToOne
    @JoinColumn(name = "manufacturer_id")
    private Manufacturer manufacturer;

    @ManyToOne
    @JoinColumn(name = "country_id")
    private Countries countries;
}

DrinkDTO:

public class DrinkDTO {

    // Fields
    //
    private String drinkName;

    private float drinkPrice;

    private String drinkAbout;

    private Packaging drinkPackaging;

    private Manufacturer drinkManufacturer;

    private Countries drinkCountries;

    // Getters and Setters
    //
    public String getDrinkName() {
        return drinkName;
    }

    public void setDrinkName(String drinkName) {
        this.drinkName = drinkName;
    }

    public float getDrinkPrice() {
        return drinkPrice;
    }

    public void setDrinkPrice(float drinkPrice) {
        this.drinkPrice = drinkPrice;
    }

    public String getDrinkAbout() {
        return drinkAbout;
    }

    public void setDrinkAbout(String drinkAbout) {
        this.drinkAbout = drinkAbout;
    }

    public Packaging getDrinkPackaging() {
        return drinkPackaging;
    }

    public void setDrinkPackaging(Packaging drinkPackaging) {
        this.drinkPackaging = drinkPackaging;
    }

    public Manufacturer getDrinkManufacturer() {
        return drinkManufacturer;
    }

    public void setDrinkManufacturer(Manufacturer drinkManufacturer) {
        this.drinkManufacturer = drinkManufacturer;
    }

    public Countries getDrinkCountries() {
        return drinkCountries;
    }

    public void setDrinkCountries(Countries drinkCountries) {
        this.drinkCountries = drinkCountries;
    }

    // toSTRING
    @Override
    public String toString() {
        return "DrinkDTO{" +
                "drinkName='" + drinkName + '\'' +
                ", drinkPrice=" + drinkPrice +
                ", drinkAbout='" + drinkAbout + '\'' +
                ", drinkPackaging=" + drinkPackaging +
                ", drinkManufacturer=" + drinkManufacturer +
                ", drinkCountries=" + drinkCountries +
                '}';
    }

CustomerController:

@GetMapping("/drinks")
List<DrinkDTO> getAllDrinks(){
    return DrinkMapper.INSTANCE.drinksToDrinksDTO(customerService.getAllDrinks());
}

BUILD.GRADLE

// Mapstruct
implementation 'org.mapstruct:mapstruct:1.3.1.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.3.1.Final'

DrinkMapper:

@Mapper
public interface DrinkMapper {

    DrinkMapper INSTANCE = Mappers.getMapper(DrinkMapper.class);

    @Mapping(source = "name", target = "drinkName")
    @Mapping(source = "price", target = "drinkPrice")
    @Mapping(source = "about", target = "drinkAbout")
    @Mapping(source = "packaging", target = "drinkPackaging")
    @Mapping(source = "manufacturer", target = "drinkManufacturer")
    @Mapping(source = "countries", target = "drinkCountries")
    DrinkDTO drinkToDrinkDTO(Drink drink);

    @Mapping(source = "drinkName", target = "name")
    @Mapping(source = "drinkPrice", target = "price")
    @Mapping(source = "drinkAbout", target = "about")
    @Mapping(source = "drinkPackaging", target = "packaging")
    @Mapping(source = "manufacturer", target = "drinkManufacturer")
    @Mapping(source = "drinkCountries", target = "countries")
    Drink drinkDTOtoDrink(DrinkDTO drinkDTO);

    @Mapping(source = "name", target = "drinkName")
    @Mapping(source = "price", target = "drinkPrice")
    @Mapping(source = "about", target = "drinkAbout")
    @Mapping(source = "packaging", target = "drinkPackaging")
    @Mapping(source = "manufacturer", target = "drinkManufacturer")
    @Mapping(source = "countries", target = "drinkCountries")
    List<DrinkDTO> drinksToDrinksDTO(List<Drink> drinks);
}

ERRORS:

@MAPSTRUCT. 源参数中不存在名为 “packaging” 的属性

英文:

I am writing an MVC REST application with Spring Boot and Hibernate. I decided to do DTO mapping using MAPSTRUCT. It seems that I did everything according to the guide, but an error is issued. What is the problem, I cannot understand. There is very little information on forums and on google.

P.S. At first I thought that the problem was in Lombok, so I removed Lombok and manually assigned getters / setters. Then the problem was not solved. I took both in the Drink class and in the DrinkDTO I prescribed getters / setters. It still didn't help.

Drink:

@Entity
@Table(name = &quot;drink&quot;, schema = &quot;public&quot;)
public class Drink {

    public Drink() { // Constructor for Hibernate

    }


    // Fields
    //
    private @Id
    @GeneratedValue
    Long id;

    @Column(name = &quot;name&quot;)
    private String name;

    @Column(name = &quot;price&quot;)
    private float price;

    @Column(name = &quot;about&quot;)
    private String about;

    @Column(name = &quot;is_deleted&quot;)
    private boolean isDeleted;

    // Relationships
    //
    @ManyToOne
    @JoinColumn(name = &quot;packaging_id&quot;)
    private Packaging packaging;

    @ManyToOne
    @JoinColumn(name = &quot;manufacturer_id&quot;)
    private Manufacturer manufacturer;

    @ManyToOne
    @JoinColumn(name = &quot;country_id&quot;)
    private Countries countries;
}

DrinkDTO:

public class DrinkDTO {

    // Fields
    //
    private String drinkName;

    private float drinkPrice;

    private String drinkAbout;

    private Packaging drinkPackaging;

    private Manufacturer drinkManufacturer;

    private Countries drinkCountries;


    // Getters and Setters
    //
    public String getDrinkName() {
        return drinkName;
    }

    public void setDrinkName(String drinkName) {
        this.drinkName = drinkName;
    }

    public float getDrinkPrice() {
        return drinkPrice;
    }

    public void setDrinkPrice(float drinkPrice) {
        this.drinkPrice = drinkPrice;
    }

    public String getDrinkAbout() {
        return drinkAbout;
    }

    public void setDrinkAbout(String drinkAbout) {
        this.drinkAbout = drinkAbout;
    }

    public Packaging getDrinkPackaging() {
        return drinkPackaging;
    }

    public void setDrinkPackaging(Packaging drinkPackaging) {
        this.drinkPackaging = drinkPackaging;
    }

    public Manufacturer getDrinkManufacturer() {
        return drinkManufacturer;
    }

    public void setDrinkManufacturer(Manufacturer drinkManufacturer) {
        this.drinkManufacturer = drinkManufacturer;
    }

    public Countries getDrinkCountries() {
        return drinkCountries;
    }

    public void setDrinkCountries(Countries drinkCountries) {
        this.drinkCountries = drinkCountries;
    }

    // toSTRING
    @Override
    public String toString() {
        return &quot;DrinkDTO{&quot; +
                &quot;drinkName=&#39;&quot; + drinkName + &#39;\&#39;&#39; +
                &quot;, drinkPrice=&quot; + drinkPrice +
                &quot;, drinkAbout=&#39;&quot; + drinkAbout + &#39;\&#39;&#39; +
                &quot;, drinkPackaging=&quot; + drinkPackaging +
                &quot;, drinkManufacturer=&quot; + drinkManufacturer +
                &quot;, drinkCountries=&quot; + drinkCountries +
                &#39;}&#39;;
    }

CustomerController:

@GetMapping(&quot;/drinks&quot;)
    List&lt;DrinkDTO&gt; getAllDrinks(){
        return DrinkMapper.INSTANCE.drinksToDrinksDTO(customerService.getAllDrinks());
    }

BUILD.GRADLE

// Mapstruct
    implementation &#39;org.mapstruct:mapstruct:1.3.1.Final&#39;
    annotationProcessor &#39;org.mapstruct:mapstruct-processor:1.3.1.Final&#39;

DrinkMapper:

@Mapper
public interface DrinkMapper {

    DrinkMapper INSTANCE = Mappers.getMapper(DrinkMapper.class);

    @Mapping(source = &quot;name&quot;, target = &quot;drinkName&quot;)
    @Mapping(source = &quot;price&quot;, target = &quot;drinkPrice&quot;)
    @Mapping(source = &quot;about&quot;, target = &quot;drinkAbout&quot;)
    @Mapping(source = &quot;packaging&quot;, target = &quot;drinkPackaging&quot;)
    @Mapping(source = &quot;manufacturer&quot;, target = &quot;drinkManufacturer&quot;)
    @Mapping(source = &quot;countries&quot;, target = &quot;drinkCountries&quot;)
    DrinkDTO drinkToDrinkDTO(Drink drink);

    @Mapping(source = &quot;drinkName&quot;, target = &quot;name&quot;)
    @Mapping(source = &quot;drinkPrice&quot;, target = &quot;price&quot;)
    @Mapping(source = &quot;drinkAbout&quot;, target = &quot;about&quot;)
    @Mapping(source = &quot;drinkPackaging&quot;, target = &quot;packaging&quot;)
    @Mapping(source = &quot;manufacturer&quot;, target = &quot;drinkManufacturer&quot;)
    @Mapping(source = &quot;countries&quot;, target = &quot;drinkCountries&quot;)
    Drink drinkDTOtoDrink(DrinkDTO drinkDTO);

    @Mapping(source = &quot;name&quot;, target = &quot;drinkName&quot;)
    @Mapping(source = &quot;price&quot;, target = &quot;drinkPrice&quot;)
    @Mapping(source = &quot;about&quot;, target = &quot;drinkAbout&quot;)
    @Mapping(source = &quot;packaging&quot;, target = &quot;drinkPackaging&quot;)
    @Mapping(source = &quot;manufacturer&quot;, target = &quot;drinkManufacturer&quot;)
    @Mapping(source = &quot;countries&quot;, target = &quot;drinkCountries&quot;)
    List&lt;DrinkDTO&gt; drinksToDrinksDTO(List&lt;Drink&gt; drinks);
}

ERRORS:
@MAPSTRUCT. 源参数中不存在名为 “packaging” 的属性

答案1

得分: 75

对于那些在使用mapstruct + lombok时遇到相同问题的人:

我也曾遇到相同的问题。原因是我也使用了Lombok插件。
无需删除它,但您必须确保在pom.xml中的<annotationProcessorPaths>中,Lombok标签位于Mapstruct标签之前。

示例(pom.xml文件的一部分):

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId> <!-- 重要 - LOMBOK在MAPSTRUCT之前 -->
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
英文:

For those, who have the same issue when using mapstruct + lombok:

I had the same issue. The reason was that I've been using Lombok plugin too.
There's no need to remove it, but you have to ensure that in pom.xml in &lt;annotationProcessorPaths&gt; Lombok tag is before the Mapstruct one.

Example (part of pom.xml file):

&lt;build&gt;
&lt;pluginManagement&gt;
&lt;plugins&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
&lt;version&gt;3.8.1&lt;/version&gt;
&lt;configuration&gt;
&lt;source&gt;${java.version}&lt;/source&gt;
&lt;target&gt;${java.version}&lt;/target&gt;
&lt;encoding&gt;${project.build.sourceEncoding}&lt;/encoding&gt;
&lt;annotationProcessorPaths&gt;
&lt;path&gt;
&lt;groupId&gt;org.projectlombok&lt;/groupId&gt; &lt;!-- IMPORTANT - LOMBOK BEFORE MAPSTRUCT --&gt;
&lt;artifactId&gt;lombok&lt;/artifactId&gt;
&lt;version&gt;${lombok.version}&lt;/version&gt;
&lt;/path&gt;
&lt;path&gt;
&lt;groupId&gt;org.mapstruct&lt;/groupId&gt;
&lt;artifactId&gt;mapstruct-processor&lt;/artifactId&gt;
&lt;version&gt;${org.mapstruct.version}&lt;/version&gt;
&lt;/path&gt;
&lt;/annotationProcessorPaths&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;
&lt;/pluginManagement&gt;
&lt;/build&gt;

答案2

得分: 7

以下是您要翻译的内容:

只是要补充一下 @Jakub Słowikowski 的回答,gradle 依赖项也会发生相同的情况。以下的顺序导致了错误:

dependencies {    
...
annotationProcessor("org.mapstruct:mapstruct-processor:${mapstructVersion}")

annotationProcessor("org.projectlombok:lombok:${lombokVersion}")
...
}

因此,我被迫调整顺序:

dependencies {    
...
annotationProcessor("org.projectlombok:lombok:${lombokVersion}")
    
annotationProcessor("org.mapstruct:mapstruct-processor:${mapstructVersion}")
...
}
英文:

Just to add to @Jakub Słowikowski answer, the same happens with gradle dependencies. The following order was causing the error:

dependencies {    
...
annotationProcessor(&quot;org.mapstruct:mapstruct-processor:${mapstructVersion}&quot;)
annotationProcessor(&quot;org.projectlombok:lombok:${lombokVersion}&quot;)
...
}

hence I was forced to switch the order:

dependencies {    
...
annotationProcessor(&quot;org.projectlombok:lombok:${lombokVersion}&quot;)
annotationProcessor(&quot;org.mapstruct:mapstruct-processor:${mapstructVersion}&quot;)
...
}

答案3

得分: 6

错误是因为您尝试映射List&lt;&gt;对象的属性,但这些属性不存在。Mapstruct足够智能,可以在知道如何映射列表内元素的情况下生成列表之间的映射器。

因此,您不需要在列表到列表的映射上指定@Mapping注释。Mapstruct将自动使用drinkToDrinkDTO映射方法。

@Mapping(...)
DrinkDTO drinkToDrinkDTO(Drink drink);

List<DrinkDTO> drinksToDrinksDTO(List<Drink> drinks);
英文:

The error comes from the fact that you tried to map properties from List&lt;&gt; objects, but those don't exist. Mapstruct is smart enough to generate mappers between lists, provided it knows how to map the elements inside the list.

So you don't need to specify @Mapping annotations on the list-to-list mapping. Mapstruct will use the drinkToDrinkDTO mapping method automatically.

@Mapping(...)
DrinkDTO drinkToDrinkDTO(Drink drink);
List&lt;DrinkDTO&gt; drinksToDrinksDTO(List&lt;Drink&gt; drinks);

答案4

得分: 1

在我的情况下,错误不是由注解处理器的声明顺序引起的,而是由于缺少Lombok注解引起的。

我有一个将Customer映射到CustomerDto的映射,但Customer缺少了getter和setter方法。

CustomerDto toCustomerDto(Customer customer);

使用以下代码

@Data
public class CustomerDto {
  ...
}

以及

public class Customer {
  ...
}

Customer类添加@Data解决了我的问题。

英文:

In my case, the error did not stem from the declaration order of the annotationProcessors but from a missing Lombok annotation.

I had a mapping for Customer to CustomerDto, but the Customer was missing getters and setters.

CustomerDto toCustomerDto(Customer customer);

With

@Data
public class CustomerDto {
  ...
}

and

public class Customer {
  ...
}

Adding @Data to the Customer class solved the issue for me.

答案5

得分: 0

尝试在@Mapper注解中添加一个uses参数,如果您还有PackagingMapper、CoutriesMapper等,可以像这样:

@Mapper(uses = {PackagingMapper.class, CountriesMapper.class, ManufacturerMapper.class})
public interface DrinkMapper{
    ....
}
英文:

Try add a uses parameter in @Mapper annotation if you also have PackakingMapper, CoutriesMapper ... , like this:

@Mapper(uses = {PackagingMapper.class, CountriesMapper.class, ManufacturerMapper.class})
public interface DrinkMapper{
....
}

答案6

得分: 0

只需将Lombok依赖放在您的pom.xml文件中的第一个位置,然后重新加载Maven项目。您不需要添加Mapstruct插件,我只是使用了依赖项。

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct-processor -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>1.5.5.Final</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.5.5.Final</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <excludes>
                    <exclude>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                    </exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

信任我,即使您在Spring Boot Maven插件配置中排除了它,您仍然可以在项目中使用Lombok。插件中的排除配置只是告诉Maven从插件的类路径中排除指定的工件。在这种情况下,Lombok工件被排除在Spring Boot Maven插件的类路径之外,但未被排除在您项目的类路径之外。
英文:

just put lombok dependencie as first dependencie in your pom.xml file

then reload maven project

you don't need to add mapstruct plugin, i just used dependencies

	&lt;dependencies&gt;
**&lt;dependency&gt;
&lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
&lt;artifactId&gt;lombok&lt;/artifactId&gt;
&lt;optional&gt;true&lt;/optional&gt;
&lt;/dependency&gt;**
&lt;!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct-processor --&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.mapstruct&lt;/groupId&gt;
&lt;artifactId&gt;mapstruct-processor&lt;/artifactId&gt;
&lt;version&gt;1.5.5.Final&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct --&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.mapstruct&lt;/groupId&gt;
&lt;artifactId&gt;mapstruct&lt;/artifactId&gt;
&lt;version&gt;1.5.5.Final&lt;/version&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;build&gt;
&lt;plugins&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
&lt;configuration&gt;
&lt;excludes&gt;
&lt;exclude&gt;
&lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
&lt;artifactId&gt;lombok&lt;/artifactId&gt;
&lt;/exclude&gt;
&lt;/excludes&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;
&lt;/build&gt;

Trust me
you can still use Lombok in your project even if you have excluded it in the Spring Boot Maven plugin configuration.
The excludes configuration in the plugin simply tells Maven to exclude the specified artifact from the plugin's classpath. In this case, the lombok artifact is being excluded from the Spring Boot Maven plugin's classpath, but it is not being excluded from your project's classpath.

答案7

得分: 0

对于那些在使用mapstruct + lombok时遇到相同问题的人<br/>
mapstruct之前添加lombok可以解决问题</b>
lombokMapstruct都基于annotation-processor,而mapstruct依赖于从lombok生成的getter和setter来生成Mapper实现。改变lombok getter和setter生成的顺序,然后再由mapstruct使用,这就是改变annotationProcessor顺序的原因!!

英文:

For those, who have the same issue when using mapstruct + lombok <br/>
<b>Adding lombok before mapstruct works as</b>
Both lombok & Mapstruct are based on annotation-processor, and mapstruct depends on getter & setter generated from lombok to generate the Mapper implementation. On changing the order lombok getter & setter are created first which are then used by mapstruct, so that why changin g order of annotationProcessor works !!

答案8

得分: 0

我也遇到了这个问题,罪魁祸首是在我的实体类上使用了

@Accessors(fluent=true)

对我来说,使用实验性的Lombok功能是我的错! @MAPSTRUCT. 源参数中不存在名为 “packaging” 的属性

英文:

I ran into this as well, and the culprit was the use of

@Accessors(fluent=true)

on my Entity classes. Serves me right for using experimental Lombok features! @MAPSTRUCT. 源参数中不存在名为 “packaging” 的属性

答案9

得分: 0

我不确定这个问题是否仍然会影响任何人。
我遇到了相同的问题,问题是由于无效的映射导致的。
就像在你的情况下,要映射映射结构接口中的packaging_id,你应该像这样提到:

@Mapping(source = "packaging.field_name", target = "drinkPackaging")

这里的packagingPackaging实体的字段名,而field_name是你想要分配的字段,它在你的包装实体中声明。
命名约定应该完全匹配,这意味着你的实体中的字段名应该与你的映射接口源属性中的字段名相同。

英文:

I was not sure if this problem still coming for anyone.
I have encountered the same problem and the issue is due to invalid mappings.
As in your case to map the packaging_id in the map struct interface you should mention like

@Mapping(source = &quot;packaging.field_name&quot; target = &quot;drinkPackaging&quot;)

here packaging is the field name of Packaging entity and field_name is whatever the field you want to assign which is declared in your packaging entity.
The naming conventions should match exactly means the field name in your entity should be the same as in your mapper interface source attribute.

答案10

得分: -2

  1. 生成DrinkDrinkDTO类的Getters / Setters(可能不使用Lombok)。

  2. 使用Gradle任务:Build构建项目。

  3. 启动项目!

英文:

Steps:

  1. Generate Getters / Setters for Drink and DrinkDTO classes(maybe without Lombok).

  2. Build project with Gradle Task: Build

  3. Start project!

huangapple
  • 本文由 发表于 2020年7月22日 21:07:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/63034956.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定