@地图结构。源参数中不存在名为 "packaging" 的 属性
@MAPSTRUCT. No property named "packaging" exists in source parameter(s)
我正在用 Spring Boot
和 Hibernate
编写 MVC
REST
应用程序。我决定使用 MAPSTRUCT
进行 DTO
映射。似乎我按照指南做了所有事情,但出现错误。什么问题,看不懂。论坛和 google.
上的信息很少
P.S。一开始以为问题出在Lombok
,于是去掉Lombok
,手动赋值getters / setters
。然后问题没有解决。我在 Drink
class 和 DrinkDTO
中都服用了 getters / setters
。还是没用。
饮料:
@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 +
'}';
}
客户控制器:
@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 = "countries", target = "drinkCountries")
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);
}
错误:
如果您还有 PackakingMapper、CoutriesMapper ...,请尝试在 @Mapper 注释中添加一个 uses 参数,如下所示:
@Mapper(uses = {PackagingMapper.class, CountriesMapper.class, ManufacturerMapper.class})
public interface DrinkMapper{
....
}
步骤:
为Drink
和DrinkDTO
生成Getters / Setters
类(可能没有Lombok
)。
使用 Gradle
任务构建项目:Build
开始项目!
错误是由于您尝试从 List<>
对象映射属性,但这些对象不存在。 Mapstruct 足够智能,可以在列表之间生成映射器,前提是它知道如何映射列表中的元素。
因此您不需要在列表到列表的映射上指定 @Mapping
注释。 Mapstruct 将自动使用 drinkToDrinkDTO
映射方法。
@Mapping(...)
DrinkDTO drinkToDrinkDTO(Drink drink);
List<DrinkDTO> drinksToDrinksDTO(List<Drink> drinks);
对于那些在使用 mapstruct
+ lombok
时遇到同样问题的人:
我遇到了同样的问题。原因是我也一直在使用 Lombok
插件。
不需要删除它,但是你必须确保 pom.xml
in <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> <!-- IMPORTANT - LOMBOK BEFORE 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>
只是添加到@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}")
...
}
我正在用 Spring Boot
和 Hibernate
编写 MVC
REST
应用程序。我决定使用 MAPSTRUCT
进行 DTO
映射。似乎我按照指南做了所有事情,但出现错误。什么问题,看不懂。论坛和 google.
P.S。一开始以为问题出在Lombok
,于是去掉Lombok
,手动赋值getters / setters
。然后问题没有解决。我在 Drink
class 和 DrinkDTO
中都服用了 getters / setters
。还是没用。
饮料:
@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 +
'}';
}
客户控制器:
@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 = "countries", target = "drinkCountries")
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);
}
错误:
如果您还有 PackakingMapper、CoutriesMapper ...,请尝试在 @Mapper 注释中添加一个 uses 参数,如下所示:
@Mapper(uses = {PackagingMapper.class, CountriesMapper.class, ManufacturerMapper.class})
public interface DrinkMapper{
....
}
步骤:
为
Drink
和DrinkDTO
生成Getters / Setters
类(可能没有Lombok
)。使用
Gradle
任务构建项目:Build
开始项目!
错误是由于您尝试从 List<>
对象映射属性,但这些对象不存在。 Mapstruct 足够智能,可以在列表之间生成映射器,前提是它知道如何映射列表中的元素。
因此您不需要在列表到列表的映射上指定 @Mapping
注释。 Mapstruct 将自动使用 drinkToDrinkDTO
映射方法。
@Mapping(...)
DrinkDTO drinkToDrinkDTO(Drink drink);
List<DrinkDTO> drinksToDrinksDTO(List<Drink> drinks);
对于那些在使用 mapstruct
+ lombok
时遇到同样问题的人:
我遇到了同样的问题。原因是我也一直在使用 Lombok
插件。
不需要删除它,但是你必须确保 pom.xml
in <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> <!-- IMPORTANT - LOMBOK BEFORE 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>
只是添加到@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}")
...
}